• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Solved] Morale System

Status
Not open for further replies.
Level 3
Joined
Apr 20, 2021
Messages
19
So I have developed a Morale System in which units gain/lose mana if they're attacking/getting attacked respectively. If a unit's mana reaches 0, the attacked and the attacking player gets a text stating that their unit/the enemy's unit has fled. They then promptly disappear from the map.

1618972457684.png


I want to revamp the system to work in a way such that the fleeing unit doesn't merely disappear, but rather they turn into uncontrollable NPCs that moves in a random direction for awhile before disappearing (so that they don't lag the game). This will add an extra layer of strategy in which you need to take care of your army's morale, otherwise they could turn into panicked obstacles during an ensuing battle and potentially hinder your attack/retreat. Could you guys help me with this?
 
Last edited:
Level 3
Joined
Apr 20, 2021
Messages
19
I don't know if it's the most efficient way to do it, but I have succeeded. What I did was make two triggers that split the system in two - one that sends the text "Fleeing" text and changes the unit to a Neutral Passive, and one that causes the now neutral unit to panic and run around before suffering a heart attack (to prevent NPCs from piling up and eventually lagging the game).

1618989391827.png

1618989437232.png


As for the added/lost morale per damage dealt/sustained, I split it into two as well.

1618989513811.png

1618989543220.png


Feel free to comment if you found a more efficient way to replicate the same results. I ended up solving my own problem, but I hope this helps another newbie like me who is trying to create a similar system that I have going on. Good luck!
 

Attachments

  • 1618989524651.png
    1618989524651.png
    10.9 KB · Views: 19
  • 1618989531217.png
    1618989531217.png
    10.9 KB · Views: 14
Level 15
Joined
Feb 2, 2009
Messages
154
Looks interesting, but keep in mind that too many concurrent Wait commands may lag the game a bit. That aside you may want to give a quick glance over location leaks in Ralle's tutorial: Things That Leak.

Only mentioning this because you mentioned that you were a "newbie" and (Random point in (Entire map)) leaks a location every time it is subsequently used, such as in the way you have posted. If the combat you are running with this system is small it should not be a big issue, but too many leaks can lead to performance issues as the game drags on.

If you are already aware of this leak or if this was just an example trigger you can ignore this, otherwise I highly recommend the tutorial I posted. Hope this helps!
 
Level 3
Joined
Apr 20, 2021
Messages
19
Looks interesting, but keep in mind that too many concurrent Wait commands may lag the game a bit. That aside you may want to give a quick glance over location leaks in Ralle's tutorial: Things That Leak.

Only mentioning this because you mentioned that you were a "newbie" and (Random point in (Entire map)) leaks a location every time it is subsequently used, such as in the way you have posted. If the combat you are running with this system is small it should not be a big issue, but too many leaks can lead to performance issues as the game drags on.

If you are already aware of this leak or if this was just an example trigger you can ignore this, otherwise I highly recommend the tutorial I posted. Hope this helps!
Thank you, it truly does help!
 
Level 25
Joined
Sep 26, 2009
Messages
2,373
This may depend on how your map is played, but personally I wouldn't use the 'Unit - Unit is attacked' event for such important system.
The reason why is because the 'Unit is attacked' event is fired before damage is dealt to the target - for example this event fires when Footman starts swinging his sword or when rifleman takes aim at the target, but does not yet shoot, or when night elf archer begins loading her bow with arrow.
This means that if you stop the unit before it actually hits the target/fires the shot, then the unit's AI will attempt to attack the target again - this will once again fire the 'Unit is attacked' event, making it very easy to spam the event.
Considering how important to your game this system may be, having the option of spamming 'Stop' command on your unit to increase the speed at which you decrease mana of the attacked unit seems like a serious hole in the system - a hole that players may abuse.

As an example, consider the trigger below. Use the trigger below in a new map and just place the peasant as Blue and for example rifleman as Red close enough to one another, so that the rifleman will attempt to attack the peasant and you will see how the game starts spamming the event. You (or any player) can of course simulate this yourself by spamming the 'Stop' command button for the unit.
  • Untitled Trigger 001
    • Events
      • Unit - Peasant 0005 <gen> Is attacked
    • Conditions
    • Actions
      • Game - Display to (All players) the text: Peasant is attacked!
      • Unit - Order (Attacking unit) to Stop.
So to solve this issue, I would base the morale system on the 'Unit takes damage' event - this event is fired when unit was actually damaged (but before its health was decreased). At best, use a damage detection system which provides a safe way to the 'Unit takes damage' event... e.g. Damage Engine 5.7.1.2

As for the part where unit is fleeing the fight, I am not sure if you want the fleeing unit to die after 30 seconds or be removed from game after 30 seconds.
Either way the solution is similar.
In the triggers below, I manually cause a specific unit (Footman) to flee and die after 30 seconds when I press Esc. In your case, you could use the Event and Conditions from your "Broken Moral Text" trigger and just set the FleeingUnit variable to (Attacked unit).

A) unit dies after 30 seconds

In the trigger I add the generic expiration timer (similar thing to what summoned units like Water Elementals have) and once it expires, it kills the unit.
The trigger orders the unit to move to some random location, but also adds the "Wander" ability to the unit. The "Wander" ability is what critters (e.g. sheep, frog) have. The ability causes the unit to move every ~8-10 seconds to some random location.

  • Start
    • Events
      • Player - Player 1 (Red) skips a cinematic sequence
    • Conditions
    • Actions
      • Set VariableSet FleeingUnit = Footman 0000 <gen>
      • Set VariableSet FleeLocation = (Random point in (Playable map area))
      • Unit - Add a 30.00 second Generic expiration timer to FleeingUnit
      • Unit - Change ownership of FleeingUnit to Neutral Passive and Change color
      • Unit - Add Wander (Neutral) to FleeingUnit
      • Unit - Order FleeingUnit to Move To FleeLocation
      • Custom script: call RemoveLocation(udg_FleeLocation)

B) unit is removed from the game after 30 seconds

The first trigger is same as in the A) option. The only difference is that the FleeingUnit is also added to the "FleeingUnitsGroup" unit group.
  • Start
    • Events
      • Player - Player 1 (Red) skips a cinematic sequence
    • Conditions
    • Actions
      • Set VariableSet FleeingUnit = Footman 0000 <gen>
      • Set VariableSet FleeLocation = (Random point in (Playable map area))
      • Unit - Add a 30.00 second Generic expiration timer to FleeingUnit
      • Unit - Change ownership of FleeingUnit to Neutral Passive and Change color
      • Unit - Add Wander (Neutral) to FleeingUnit
      • Unit - Order FleeingUnit to Move To FleeLocation
      • Unit Group - Add FleeingUnit to FleeingUnitsGroup
      • Custom script: call RemoveLocation(udg_FleeLocation)

This trigger checks if the dying unit is in the FleeingUnitsGroup unit group and if so, it immediately removes the unit from the game (and also from the unit group to keep it clean and tidy). Thanks to this, the unit won't even have time to play it's death animation before it is removed.
  • Check
    • Events
      • Unit - A unit Dies
    • Conditions
      • ((Triggering unit) is in FleeingUnitsGroup.) Equal to True
    • Actions
      • Unit Group - Remove (Triggering unit) from FleeingUnitsGroup.
      • Unit - Remove (Triggering unit) from the game
 
Level 3
Joined
Apr 20, 2021
Messages
19
This may depend on how your map is played, but personally I wouldn't use the 'Unit - Unit is attacked' event for such important system.
The reason why is because the 'Unit is attacked' event is fired before damage is dealt to the target - for example this event fires when Footman starts swinging his sword or when rifleman takes aim at the target, but does not yet shoot, or when night elf archer begins loading her bow with arrow.
This means that if you stop the unit before it actually hits the target/fires the shot, then the unit's AI will attempt to attack the target again - this will once again fire the 'Unit is attacked' event, making it very easy to spam the event.
Considering how important to your game this system may be, having the option of spamming 'Stop' command on your unit to increase the speed at which you decrease mana of the attacked unit seems like a serious hole in the system - a hole that players may abuse.

As an example, consider the trigger below. Use the trigger below in a new map and just place the peasant as Blue and for example rifleman as Red close enough to one another, so that the rifleman will attempt to attack the peasant and you will see how the game starts spamming the event. You (or any player) can of course simulate this yourself by spamming the 'Stop' command button for the unit.
  • Untitled Trigger 001
    • Events
      • Unit - Peasant 0005 <gen> Is attacked
    • Conditions
    • Actions
      • Game - Display to (All players) the text: Peasant is attacked!
      • Unit - Order (Attacking unit) to Stop.
So to solve this issue, I would base the morale system on the 'Unit takes damage' event - this event is fired when unit was actually damaged (but before its health was decreased). At best, use a damage detection system which provides a safe way to the 'Unit takes damage' event... e.g. Damage Engine 5.7.1.2

As for the part where unit is fleeing the fight, I am not sure if you want the fleeing unit to die after 30 seconds or be removed from game after 30 seconds.
Either way the solution is similar.
In the triggers below, I manually cause a specific unit (Footman) to flee and die after 30 seconds when I press Esc. In your case, you could use the Event and Conditions from your "Broken Moral Text" trigger and just set the FleeingUnit variable to (Attacked unit).

A) unit dies after 30 seconds

In the trigger I add the generic expiration timer (similar thing to what summoned units like Water Elementals have) and once it expires, it kills the unit.
The trigger orders the unit to move to some random location, but also adds the "Wander" ability to the unit. The "Wander" ability is what critters (e.g. sheep, frog) have. The ability causes the unit to move every ~8-10 seconds to some random location.

  • Start
    • Events
      • Player - Player 1 (Red) skips a cinematic sequence
    • Conditions
    • Actions
      • Set VariableSet FleeingUnit = Footman 0000 <gen>
      • Set VariableSet FleeLocation = (Random point in (Playable map area))
      • Unit - Add a 30.00 second Generic expiration timer to FleeingUnit
      • Unit - Change ownership of FleeingUnit to Neutral Passive and Change color
      • Unit - Add Wander (Neutral) to FleeingUnit
      • Unit - Order FleeingUnit to Move To FleeLocation
      • Custom script: call RemoveLocation(udg_FleeLocation)

B) unit is removed from the game after 30 seconds

The first trigger is same as in the A) option. The only difference is that the FleeingUnit is also added to the "FleeingUnitsGroup" unit group.
  • Start
    • Events
      • Player - Player 1 (Red) skips a cinematic sequence
    • Conditions
    • Actions
      • Set VariableSet FleeingUnit = Footman 0000 <gen>
      • Set VariableSet FleeLocation = (Random point in (Playable map area))
      • Unit - Add a 30.00 second Generic expiration timer to FleeingUnit
      • Unit - Change ownership of FleeingUnit to Neutral Passive and Change color
      • Unit - Add Wander (Neutral) to FleeingUnit
      • Unit - Order FleeingUnit to Move To FleeLocation
      • Unit Group - Add FleeingUnit to FleeingUnitsGroup
      • Custom script: call RemoveLocation(udg_FleeLocation)

This trigger checks if the dying unit is in the FleeingUnitsGroup unit group and if so, it immediately removes the unit from the game (and also from the unit group to keep it clean and tidy). Thanks to this, the unit won't even have time to play it's death animation before it is removed.
  • Check
    • Events
      • Unit - A unit Dies
    • Conditions
      • ((Triggering unit) is in FleeingUnitsGroup.) Equal to True
    • Actions
      • Unit Group - Remove (Triggering unit) from FleeingUnitsGroup.
      • Unit - Remove (Triggering unit) from the game
I wasn't aware of the Wander ability, it's exactly what I was trying to find when I first conceptualized the Morale System, thank you! I doubt that the players would be able to actually abuse this loophole with all of the micro and macro management going around, but I will definitely patch it up using the trigger you've suggested as a point of reference. As for the fleeing unit part, I like to think that they suffer a massive heart attack after 30 seconds from the immense stress that they received from warfare. It's a clever way to clear the fleeing units from the game and a bit more realistic than just having them cease to exist HAHAHAHA.
 
Status
Not open for further replies.
Top