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

[Trigger] really weird bug with "replace unit" on creeps

Status
Not open for further replies.
Level 21
Joined
Mar 29, 2020
Messages
1,237
hey,

So I made a spell that issues an order to the target -at lev 1 to move to a random point, and at lev2,3 to attack a random enemy of the caster . I also added to lev 3 of the spell "replace unit" so it would also take the target unit out of any control groups its in (with help from @Zwiebelchen ). when I cast level 3 on creeps a super weird bug happens (consistently) -

for every time casted it creates an invisible (even with detecting units), unselectable copy of the unit who chases the caster and attacks it (and only it) endlessly (or until the caster goes into a zeppelin or something or dies).

I changed the ability so it doesn't make neutral hostiles get replaced (which doesn't matter for them anyways...) but I was just curious if anyone has any idea what's causing this...

the ability:

  • Voodoo Doll
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Voodoo Doll
    • Actions
      • Set Temptarget = (Target unit of ability being cast)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Owner of Temptarget) Equal to Neutral Hostile
        • Then - Actions
          • If ((Temptarget is Sleeping) Equal to True) then do (Unit - Wake up Temptarget) else do (Do nothing)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Level of Voodoo Doll for (Triggering unit)) Greater than or equal to 2
            • Then - Actions
              • Set Temp_PlayerGroup = (All enemies of (Triggering player))
              • Custom script: set bj_wantDestroyGroup = true
              • Unit - Order (Last replaced unit) to Attack (Random unit from (Units in (Playable map area) owned by (Random player from Temp_PlayerGroup)))
              • Custom script: call DestroyForce(udg_Temp_PlayerGroup)
            • Else - Actions
          • Set TempPoint = (Random point in (Playable map area))
          • Unit - Order Temptarget to Move To TempPoint
          • Custom script: call RemoveLocation (udg_TempPoint)
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Level of Voodoo Doll for (Triggering unit)) Equal to 1
            • Then - Actions
              • Selection - Remove Temptarget from selection for (Owner of Temptarget)
              • Set TempPoint = (Random point in (Playable map area))
              • Unit - Order Temptarget to Move To TempPoint
              • Custom script: call RemoveLocation (udg_TempPoint)
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Level of Voodoo Doll for (Triggering unit)) Equal to 2
                • Then - Actions
                  • Selection - Remove Temptarget from selection for (Owner of Temptarget)
                  • Custom script: set bj_wantDestroyGroup = true
                  • Unit - Order Temptarget to Attack (Random unit from (Units in (Playable map area) owned by (Random player from (All enemies of (Owner of (Triggering unit))))))
                • Else - Actions
                  • Set UnitType = (Unit-type of Temptarget)
                  • Unit - Replace Temptarget with a UnitType using The old unit's relative life and mana
                  • Set Temp_PlayerGroup = (All enemies of (Triggering player))
                  • Custom script: set bj_wantDestroyGroup = true
                  • Unit - Order (Last replaced unit) to Attack (Random unit from (Units in (Playable map area) owned by (Random player from Temp_PlayerGroup)))
                  • Special Effect - Create a special effect attached to the head of (Last replaced unit) using Objects\Spawnmodels\Other\ToonBoom\ToonBoom.mdl
                  • Custom script: call DestroyForce(udg_Temp_PlayerGroup)
                  • Special Effect - Destroy (Last created special effect)

thanks!
 
Last edited:
Level 25
Joined
Sep 26, 2009
Messages
2,383
Hmm, this is indeed strange.
From my tests, what actually happens is that the unit, which was replaced, is not removed from the game but is actually just hidden. The hidden unit either retains its order (attacking spell source) or attacks you because it is in range of you and awake. Ordering the hidden unit to stop did nothing.

I created a trigger that fires when my caster is damaged. The trigger prints Handle ID of the damage source.
This way I found out that the old unit is just hidden by checking the target's handle ID before I cast the spell on it and then checking the handle ID of the new (visible) unit and handle ID of the old (hidden) unit.
The handle ID matched that of the old unit.
The trigger that prints handle IDs was also set up to unhide the damage source... well, it made the old unit visible again.
See the triggers below:

This was simulating your level 3 spell
  • Spell test
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Custom Spell
    • Actions
      • Game - Display to (All players) the text: spell fired
      • Set VariableSet target = (Target unit of ability being cast)
      • Unit - Replace target with a (Unit-type of target) using The new unit's max life and mana
      • Unit - Pause target
      • Set VariableSet targetEnemies = (All enemies of (Triggering player).)
      • Set VariableSet newTarget = (Random unit from (Units in (Playable map area) owned by (Random player from targetEnemies)))
      • Special Effect - Create a special effect attached to the origin of newTarget using Abilities\Spells\Undead\DarkRitual\DarkRitualCaster.mdl
      • Special Effect - Destroy (Last created special effect)
      • Unit - Order (Last replaced unit) to Attack target
      • Special Effect - Create a special effect attached to the origin of (Last replaced unit) using Abilities\Spells\Undead\AnimateDead\AnimateDeadTarget.mdl
      • Special Effect - Destroy (Last created special effect)
      • Custom script: call DestroyForce(udg_targetEnemies)
This was detecting anyone that attacked the caster of the spell above
  • Unit
    • Events
      • Unit - Peasant 0005 <gen> Takes damage
    • Conditions
    • Actions
      • Set VariableSet handle = (Damage source)
      • Game - Display to (All players) the text: ((String((Unit-type of (Damage source)))) + ( + (String((Key handle.)))))
      • Unit - Unhide (Damage source)


As for how to fix this - I just paused the old unit after it was replaced (variable still pointed to the old unit). Perhaps removing the unit entirely from game is also possible.
I do not know if this is an issue of only neutral hostile units or any player.
 
Level 25
Joined
Sep 26, 2009
Messages
2,383
I am not sure if it is constantly leaking. For example when I had trigger that replaced my currently selected unit and immediately after replacing unhid the old unit, no unit was unhid. The handle ID of the old unit was still saved, but things like who owned the unit, unit type, etc. were lost.
It may be a special case that when replaced the way it is in your trigger, the unit remains in game.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,580
Replace unit isn't anything fancy anyway, right?

I think this mimics it's behavior, at least for the old unit's relative life/mana setup:
  • replace target
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
    • Actions
      • Set VariableSet target = (Target unit of ability being cast)
      • Set VariableSet life = (Percentage life of target)
      • Set VariableSet mana = (Percentage mana of target)
      • Set VariableSet angle = (Facing of target)
      • Set VariableSet point = (Position of target)
      • Unit - Hide target
      • Unit - Create 1 (Unit-type of target) for (Owner of target) at point facing angle degrees
      • Custom script: call RemoveLocation (udg_point)
      • Unit - Set life of (Last created unit) to life%
      • Unit - Set mana of (Last created unit) to mana%
      • Unit - Remove target from the game
 
Status
Not open for further replies.
Top