• 🏆 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!

Unit Recreation at position of Dying Unit

Status
Not open for further replies.
Level 3
Joined
Dec 11, 2012
Messages
43
Hello there,

I am trying to create specific units in a unit group to be revived at the position of their death.

help.png

As you see player 12 brown are my citizens when they are attacked they change to dark green which is my evil force to fight back. I have this part working now where I am stuck here is when the unit dies it does not create the unit that died for player brown at the position of where it died. Nothing happens this is where I am having trouble trying to get this part to work.
The reason why I have these units added to attackedcitizen which is a variable unit group is because my forces of evil will have many different type of units and I only want the units that were originally from brown to be recreated which is why I created the unit group. Hopefully someone can help me out!
 
Level 11
Joined
Jun 2, 2004
Messages
849
You're doing too much in a single trigger. You need a second one, with the event "A unit dies", and the condition "Dying unit belongs to attacked citizen equal to true" (a boolean comparison, unit belongs to unit group).
 
Level 13
Joined
Oct 12, 2016
Messages
769
I gotcha covered.
The biggest problem with this is that you are using the wrong event, and you should be using "Triggering unit" in your actions.
Nothing is dying in that function.
This function is also more easily done in separate triggers.
Check this out:
  • Respawn Citizens
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Owner of (Triggering unit)) Equal to Player 11 (Dark Green)
    • Actions
      • Wait 3.00 seconds
      • Set TempPoint = (Position of (Triggering unit))
      • Unit - Create 1 (Unit-type of (Triggering unit)) for Player 12 (Brown) at TempPoint facing (Facing of (Triggering unit)) degrees
      • Custom script: call RemoveLocation(udg_TempPoint)
  • Aggro Citizens
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • (Owner of (Triggering unit)) Equal to Player 12 (Brown)
    • Actions
      • Unit - Change ownership of (Triggering unit) to Player 11 (Dark Green) and Retain color
Those 2 triggers should give you what you want.
I do advise also advise making them change to player 11 if a player casts a negative spell on them.
Use this idea to figure that out.

Also, that "TempPoint" function with variable is to avoid memory leaks on your map.
Memory leaks are bad. They create lag.
 
Last edited:
Level 3
Joined
Dec 11, 2012
Messages
43
Wouldn't this be a problem? As I stated before my citzens are the only units I want to be recreated. With your trigger here it seems any unit of dark green that gets killed will be recreated. Dark Green is more then just the citizens units and I created that unit group only so the trigger will recreate the citizens only which is what I thought I would achieve by the condition
(dying unit) equal to random unit from attackedcitizen which is a variable unit group. and adding under actions add triggering unit to attacked citizens.
 
Level 13
Joined
Oct 12, 2016
Messages
769
You can then just put in a unit-type condition for the respawn trigger.
This would make it so that only units of certain types will respawn.
Something like this:
  • Respawn Citizens
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Owner of (Triggering unit)) Equal to Player 11 (Dark Green)
      • Or - Any (Conditions) are true
        • Conditions
          • (Unit-type of (Triggering unit)) Equal to Soldier
          • (Unit-type of (Triggering unit)) Equal to Citizen
    • Actions
      • Wait 3.00 seconds
      • Set TempPoint = (Position of (Triggering unit))
      • Unit - Create 1 (Unit-type of (Triggering unit)) for Player 12 (Brown) at TempPoint facing (Facing of (Triggering unit)) degrees
      • Custom script: call RemoveLocation(udg_TempPoint)
Just make sure the citizens are unique from player 11's units.
There's no shame in making duplicate versions of a unit for triggering purposes, either.
 
Last edited:
Level 3
Joined
Dec 11, 2012
Messages
43
You can then just put in a unit-type condition for the respawn trigger.
This would make it so that only units of certain types will respawn.
Something like this:
  • Respawn Citizens
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Owner of (Triggering unit)) Equal to Player 11 (Dark Green)
      • Or - Any (Conditions) are true
        • Conditions
          • (Unit-type of (Triggering unit)) Equal to Soldier
          • (Unit-type of (Triggering unit)) Equal to Citizen
    • Actions
      • Wait 3.00 seconds
      • Set TempPoint = (Position of (Triggering unit))
      • Unit - Create 1 (Unit-type of (Triggering unit)) for Player 12 (Brown) at TempPoint facing (Facing of (Triggering unit)) degrees
      • Custom script: call RemoveLocation(udg_TempPoint)
Just make sure the citizens are unique from player 11's units.
There's no shame in making duplicate versions of a unit for triggering purposes, either.

Just curious to know how come you made a point variable?


My friends I have achieved what I was trying to do with this trigger.
help.png

Photo for Reference.
 

  • Init_Hash
    • Events
      • Event - Map Initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set Hash = (last created hashtable)
      • Set Key = 0
  • Attacking Citizens Revive
    • Events
    • Conditions
    • Actions
      • Custom Script - set udg_Key = GetHandleId(GetExpiredTimer())
      • Custom Script - set bj_lastCreatedUnit = CreateUnit(Player(11), LoadInteger(udg_HASH, udg_Key, 0), LoadReal(udg_HASH, udg_Key, 1), LoadReal(udg_HASH, udg_Key, 2), LoadReal(udg_HASH, udg_Key, 3))
      • Hashtable - Flush udg_Key of Hash
      • Custom Script - call DestroyTimer(GetExpiredTimer())
  • Attacking Citizens
    • Events
      • Unit - A unit owned by Player 12 (Brown) Is attacked
      • Unit - A unit dies
    • Conditions
    • Actions
      • Custom Script - if GetTriggerEventId() == EVENT_PLAYER_UNIT_ATTACKED then
      • Unit Group - Add (Triggering Unit) to attackedunitcitizen
      • Unit - Change ownership of (Triggering Unit) to Player 11 (Dark Green) and Change color)
      • Custom Script - elseif GetTriggerEventId() == EVENT_PLAYER_UNIT_DEATH and IsUnitInGroup(GetTriggerUnit(), udg_attackedunitcitizen) then
      • Custom Script - set bj_lastCreatedTimer = CreateTimer()
      • Custom Script - call TimerStart(bj_lastCreatedTimer, 3.00, false, function Trig_Attacking_Citizens_Revive_Actions)
      • Hashtable - Save (Unit type of (Triggering Unit)) as 0 of Key(last created Timer) in Hash
      • Custom Script - call SaveReal(udg_Hash, GetHandleId(bj_lastCreatedTimer), 1, GetUnitX(GetTriggerUnit()))
      • Custom Script - call SaveReal(udg_Hash, GetHandleId(bj_lastCreatedTimer), 2, GetUnitY(GetTriggerUnit()))
      • Hashtable - Save (Facing of (Triggering Unit)) as 3 of Key(last created Timer) in Hash
      • Custom Script - endif
 
Level 3
Joined
Dec 11, 2012
Messages
43
It's because points cause memory leaks. If there are a lot of memory leaks, it lags up your game and eventually can cause a crash.
Notice I immediately remove that point location.
This should get you started on it:
Things That Leak
The trigger I took a screenshot and said it works. It's creating point variables?


  • Init_Hash
    • Events
      • Event - Map Initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set Hash = (last created hashtable)
      • Set Key = 0
  • Attacking Citizens Revive
    • Events
    • Conditions
    • Actions
      • Custom Script - set udg_Key = GetHandleId(GetExpiredTimer())
      • Custom Script - set bj_lastCreatedUnit = CreateUnit(Player(11), LoadInteger(udg_HASH, udg_Key, 0), LoadReal(udg_HASH, udg_Key, 1), LoadReal(udg_HASH, udg_Key, 2), LoadReal(udg_HASH, udg_Key, 3))
      • Hashtable - Flush udg_Key of Hash
      • Custom Script - call DestroyTimer(GetExpiredTimer())
  • Attacking Citizens
    • Events
      • Unit - A unit owned by Player 12 (Brown) Is attacked
      • Unit - A unit dies
    • Conditions
    • Actions
      • Custom Script - if GetTriggerEventId() == EVENT_PLAYER_UNIT_ATTACKED then
      • Unit Group - Add (Triggering Unit) to attackedunitcitizen
      • Unit - Change ownership of (Triggering Unit) to Player 11 (Dark Green) and Change color)
      • Custom Script - elseif GetTriggerEventId() == EVENT_PLAYER_UNIT_DEATH and IsUnitInGroup(GetTriggerUnit(), udg_attackedunitcitizen) then
      • Custom Script - set bj_lastCreatedTimer = CreateTimer()
      • Custom Script - call TimerStart(bj_lastCreatedTimer, 3.00, false, function Trig_Attacking_Citizens_Revive_Actions)
      • Hashtable - Save (Unit type of (Triggering Unit)) as 0 of Key(last created Timer) in Hash
      • Custom Script - call SaveReal(udg_Hash, GetHandleId(bj_lastCreatedTimer), 1, GetUnitX(GetTriggerUnit()))
      • Custom Script - call SaveReal(udg_Hash, GetHandleId(bj_lastCreatedTimer), 2, GetUnitY(GetTriggerUnit()))
      • Hashtable - Save (Facing of (Triggering Unit)) as 3 of Key(last created Timer) in Hash
      • Custom Script - endif

Woah woah that is a lot and I appreciate you showing me this but can you break it down for me I don't understand what these custom scripts and the hashtable are and what they are doing?
 
Sorry, I tend to use JASS (vJASS, specifically) instead of GUI,

The trigger I took a screenshot and said it works. It's creating point variables?

  • Init_Hash
    • Events
      • Event - Map Initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set Hash = (last created hashtable)
      • Set Key = 0
  • Attacking Citizens Revive
    • Events
    • Conditions
    • Actions
      • Custom Script - set udg_Key = GetHandleId(GetExpiredTimer())
      • Custom Script - set bj_lastCreatedUnit = CreateUnit(Player(11), LoadInteger(udg_HASH, udg_Key, 0), LoadReal(udg_HASH, udg_Key, 1), LoadReal(udg_HASH, udg_Key, 2), LoadReal(udg_HASH, udg_Key, 3))
      • Hashtable - Flush udg_Key of Hash
      • Custom Script - call DestroyTimer(GetExpiredTimer())
  • Attacking Citizens
    • Events
      • Unit - A unit owned by Player 12 (Brown) Is attacked
      • Unit - A unit dies
    • Conditions
    • Actions
      • Custom Script - if GetTriggerEventId() == EVENT_PLAYER_UNIT_ATTACKED then
      • Unit Group - Add (Triggering Unit) to attackedunitcitizen
      • Unit - Change ownership of (Triggering Unit) to Player 11 (Dark Green) and Change color)
      • Custom Script - elseif GetTriggerEventId() == EVENT_PLAYER_UNIT_DEATH and IsUnitInGroup(GetTriggerUnit(), udg_attackedunitcitizen) then
      • Custom Script - set bj_lastCreatedTimer = CreateTimer()
      • Custom Script - call TimerStart(bj_lastCreatedTimer, 3.00, false, function Trig_Attacking_Citizens_Revive_Actions)
      • Hashtable - Save (Unit type of (Triggering Unit)) as 0 of Key(last created Timer) in Hash
      • Custom Script - call SaveReal(udg_Hash, GetHandleId(bj_lastCreatedTimer), 1, GetUnitX(GetTriggerUnit()))
      • Custom Script - call SaveReal(udg_Hash, GetHandleId(bj_lastCreatedTimer), 2, GetUnitY(GetTriggerUnit()))
      • Hashtable - Save (Facing of (Triggering Unit)) as 3 of Key(last created Timer) in Hash
      • Custom Script - endif

Woah woah that is a lot and I appreciate you showing me this but can you break it down for me I don't understand what these custom scripts and the hashtable are and what they are doing?

  • Init_Hash
    • Events
      • Event - Map Initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set Hash = (last created hashtable)
      • Set Key = 0
I initialize a hashtable for storing of data. Uninitialized hashtables won't hold anything so I set it to an initialized one.

  • Attacking Citizens Revive
    • Events
    • Conditions
    • Actions
      • Custom Script - set udg_Key = GetHandleId(GetExpiredTimer())
      • Custom Script - set bj_lastCreatedUnit = CreateUnit(Player(11), LoadInteger(udg_HASH, udg_Key, 0), LoadReal(udg_HASH, udg_Key, 1), LoadReal(udg_HASH, udg_Key, 2), LoadReal(udg_HASH, udg_Key, 3))
      • Hashtable - Flush udg_Key of Hash
      • Custom Script - call DestroyTimer(GetExpiredTimer())
That trigger is just for show. I get a key and create a Player 12 unit that matches one that had died earlier. I just use the actions field as my handler function. (You'll see what I mean later).

  • Attacking Citizens
    • Events
      • Unit - A unit owned by Player 12 (Brown) Is attacked
      • Unit - A unit dies
    • Conditions
    • Actions
      • Custom Script - if GetTriggerEventId() == EVENT_PLAYER_UNIT_ATTACKED then
      • Unit Group - Add (Triggering Unit) to attackedunitcitizen
      • Unit - Change ownership of (Triggering Unit) to Player 11 (Dark Green) and Change color)
      • Custom Script - elseif GetTriggerEventId() == EVENT_PLAYER_UNIT_DEATH and IsUnitInGroup(GetTriggerUnit(), udg_attackedunitcitizen) then
      • Custom Script - set bj_lastCreatedTimer = CreateTimer()
      • Custom Script - call TimerStart(bj_lastCreatedTimer, 3.00, false, function Trig_Attacking_Citizens_Revive_Actions)
      • Hashtable - Save (Unit type of (Triggering Unit)) as 0 of Key(last created Timer) in Hash
      • Custom Script - call SaveReal(udg_Hash, GetHandleId(bj_lastCreatedTimer), 1, GetUnitX(GetTriggerUnit()))
      • Custom Script - call SaveReal(udg_Hash, GetHandleId(bj_lastCreatedTimer), 2, GetUnitY(GetTriggerUnit()))
      • Hashtable - Save (Facing of (Triggering Unit)) as 3 of Key(last created Timer) in Hash
      • Custom Script - endif
(Maybe the only event to look out for is the death of a player 11 unit, instead of a generic one). In the actions part, I check if the event that fired was the former (attacked). If not, I also check if the event was the latter(death) and check if the unit was in the attackedunitcitizen group. If so, I create a timer and start it, making it end in 3.00 seconds. When 3.00 seconds has elapsed, and it will elapse once since it will NOT repeat, the handler function will be called, obtaining the data stored in the timer. After that happens, I save the necessary data in the hashtable as shown above.

  • Hashtable - Flush udg_Key of Hash
  • Custom Script - call DestroyTimer(GetExpiredTimer())
The lines above will clear the leftover data and destroy the expiring timer so as to not cause memory leaks. (Maybe 0.4 kb)
Hopefully, I made the script above MUI (Multi-unit instanceable). :)
 
Status
Not open for further replies.
Top