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

[Trigger] Wierd malfunction with Assassinate spell-trigger...

Status
Not open for further replies.
Level 2
Joined
Oct 13, 2010
Messages
9
Hey guys!
When I was working on my Bounty Hunter hero I ran into some problems in one of his triggers, Assassinate. It's a pretty easy ability. You deal damage, if target dies, you move to target unit's location.
However, I decided to spice it up a bit, so I mixed in some synergy with his first spell, Bounty scan, which added random units from an area to a unit group (Unit_Group_Bounty_Scan) and then awarded you extra gold if you killed units from this unit group with assassinate.

The problem:
-If you kill an ordinary unit with this ability, it works exactly as intended.
-BUT if you kill an unit from the unit group "Bounty scan", you won't move to the targets location.

I've been trying to get it working, but it just won't. Don't have any clue of what might cause this problem either, heck, I even gain the extra gold from the kill and the floating text appears! From what I know, the other triggers aren't the problem either... But I can post them too if needed.

Any help is greatly appreciated! :csmile:

  • Assassinate
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Assassinate
      • (Level of Assassinate for (Triggering unit)) Not equal to 0
    • Actions
      • -------- - --------
      • -------- Variables --------
      • -------- - --------
      • Set Casting_Unit = (Triggering unit)
      • Set Target_Unit = (Target unit of ability being cast)
      • Set Spell_Level = (Level of Assassinate for Casting_Unit)
      • Set Loc[1] = (Position of Target_Unit)
      • Set Damage_Primary = (75 x Spell_Level)
      • -------- Damage secondary is the amount of extra gold bounty the player will be awarded if he kills the target with assassinate. --------
      • Set Damage_Secondary = (((Owner of Casting_Unit) Current gold) + (5 x Spell_Level))
      • -------- - --------
      • -------- If target is Allied. --------
      • -------- - --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Target_Unit belongs to an enemy of (Owner of Casting_Unit)) Equal to False
        • Then - Actions
          • Unit - Move Casting_Unit instantly to Loc[1]
        • Else - Actions
      • -------- - --------
      • -------- Hostile --------
      • -------- - --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Target_Unit belongs to an enemy of (Owner of Casting_Unit)) Equal to True
        • Then - Actions
          • -------- - --------
          • -------- Damage --------
          • -------- - --------
          • Unit - Cause Casting_Unit to damage Target_Unit, dealing (Real(Damage_Primary)) damage of attack type Normal and damage type Normal
          • -------- - --------
          • -------- - --------
          • Special Effect - Create a special effect at Loc[1] using Abilities\Spells\Orc\FeralSpirit\feralspiritdone.mdl
          • Special Effect - Destroy (Last created special effect)
          • Special Effect - Create a special effect at Loc[1] using Objects\Spawnmodels\Human\HumanBlood\BloodElfSpellThiefBlood.mdl
          • Special Effect - Destroy (Last created special effect)
          • -------- - --------
          • -------- - --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Target_Unit is dead) Equal to True
            • Then - Actions
              • Unit - Move Casting_Unit instantly to Loc[1]
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Or - Any (Conditions) are true
                    • Conditions
                      • (Target_Unit is in Unit_Group_Bounty_Scan[1]) Equal to True
                      • (Target_Unit is in Unit_Group_Bounty_Scan[2]) Equal to True
                      • (Target_Unit is in Unit_Group_Bounty_Scan[3]) Equal to True
                      • (Target_Unit is in Unit_Group_Bounty_Scan[4]) Equal to True
                      • (Target_Unit is in Unit_Group_Bounty_Scan[5]) Equal to True
                • Then - Actions
                  • Player - Set (Owner of Casting_Unit) Current gold to Damage_Secondary
                  • -------- - --------
                  • Floating Text - Create floating text that reads (String((5 x Spell_Level))) above Target_Unit with Z offset 0.00, using font size 10.00, color (0.00%, 75.00%, 75.00%), and 0.00% transparency
                  • Floating Text - Change (Last created floating text): Disable permanence
                  • Floating Text - Change the lifespan of (Last created floating text) to 4.00 seconds
                  • Floating Text - Change the fading age of (Last created floating text) to 2.00 seconds
                  • -------- - --------
                  • Special Effect - Create a special effect at Loc[1] using Abilities\Spells\Other\Transmute\PileofGold.mdl
                  • Special Effect - Destroy (Last created special effect)
                • Else - Actions
            • Else - Actions
        • Else - Actions
      • -------- - --------
      • -------- Clean-up --------
      • -------- - --------
      • Set Casting_Unit = No unit
      • Set Target_Unit = No unit
      • Set Spell_Level = 0
      • Set Damage_Primary = 0
      • Set Damage_Secondary = 0
      • Custom script: call RemoveLocation(udg_Loc[1])
/Zowjos
 
Level 2
Joined
Oct 13, 2010
Messages
9
Hmmm... is that so... :cneut:
Well... come to think of it, maybe it has something to do with this trigger:
  • Unit in Unit Group dies
    • Events
      • Unit - A unit Dies
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • ((Triggering unit) is in Unit_Group_Bounty_Scan[1]) Equal to True
          • ((Triggering unit) is in Unit_Group_Bounty_Scan[2]) Equal to True
          • ((Triggering unit) is in Unit_Group_Bounty_Scan[3]) Equal to True
          • ((Triggering unit) is in Unit_Group_Bounty_Scan[4]) Equal to True
          • ((Triggering unit) is in Unit_Group_Bounty_Scan[5]) Equal to True
    • Actions
      • -------- - --------
      • -------- Variables --------
      • -------- - --------
      • Set Casting_Unit = (Triggering unit)
      • Set Loc[1] = (Position of Casting_Unit)
      • For each (Integer A) from 1 to 5, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Casting_Unit is in Unit_Group_Bounty_Scan[(Integer A)]) Equal to True
            • Then - Actions
              • Set Integer = (Integer A)
            • Else - Actions
      • Set Damage_Primary = (Integer x 35)
      • Set Spell_Aoe = 175
      • -------- - --------
      • -------- - --------
      • Unit Group - Pick every unit in (Units within (Real(Spell_Aoe)) of Loc[1] matching ((((Matching unit) belongs to an enemy of (Owner of Casting_Unit)) Equal to False) and (((Matching unit) is alive) Equal to True))) and do (Actions)
        • Loop - Actions
          • Unit - Cause Casting_Unit to damage (Picked unit), dealing (Real(Damage_Primary)) damage of attack type Spells and damage type Normal
      • Special Effect - Create a special effect at Loc[1] using Abilities\Spells\Other\Incinerate\FireLordDeathExplode.mdl
      • Special Effect - Destroy (Last created special effect)
      • -------- - --------
      • -------- Clean-up --------
      • -------- - --------
      • Set Casting_Unit = No unit
      • Set Integer = 0
      • Set Damage_Primary = 0
      • Set Spell_Aoe = 0
      • Custom script: call RemoveLocation(udg_Loc[1])
A brief explanation of the trigger:
Units in the Bounty unit group "explode" (not really, but the spell description says so at least... :cwink:) upon death, dealing damage depending on which unit group it is in. (When the spell is cast they are added to the Unit group with the same array as the level of the spell.)

Anyway, thanks for the quick reply!

Ninja-edit:
I guess I'll better just post all of the "Bounty scan" triggers... Sorry for the huge wall of text... :-/

Trigger no.1
-Adds the units under the targetted area to a unit group.

  • Bounty Scan
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Bounty Scan
      • (Level of Bounty Scan for (Triggering unit)) Not equal to 0
    • Actions
      • -------- - --------
      • -------- Variables --------
      • -------- - --------
      • Set Casting_Unit = (Triggering unit)
      • Set Spell_Level = (Level of Bounty Scan for Casting_Unit)
      • Set Spell_Aoe = (125 + (100 x Spell_Level))
      • Set Loc[1] = (Target point of ability being cast)
      • -------- The Number of targets marked with "Bounty". Subtract chosen targets from this score. --------
      • Set Damage_Primary = Spell_Level
      • -------- Subtract prioritised targets from Damage_primary score. --------
      • Set Damage_Secondary = (Damage_Primary - (Number of units in (Units within (Real(Spell_Aoe)) of Loc[1] matching (((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of (Owner of Casting_Unit)) Equal to True)) and ((((Matching unit) is A Hero) Equal
      • -------- - --------
      • -------- Pick units within spell_Aoe and add to a unit group to keep track on when (if) they die --------
      • -------- Boss/Elite Units --------
      • Unit Group - Pick every unit in (Random Damage_Primary units from (Units within (Real(Spell_Aoe)) of Loc[1] matching (((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of (Owner of Casting_Unit)) Equal to True)) and ((((Matching unit) is A Hero) Equal to and do (Actions)
        • Loop - Actions
          • -------- The array of the Unit group will be the same as the spell's level in order to keep track of how much the explosion damage will be. --------
          • -------- - --------
          • Unit Group - Add (Picked unit) to Unit_Group_Bounty_Scan[Spell_Level]
      • -------- - --------
      • -------- Normal Units --------
      • -------- - --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Damage_Secondary Greater than 0
        • Then - Actions
          • Unit Group - Pick every unit in (Random Damage_Secondary units from (Units within (Real(Spell_Aoe)) of Loc[1] matching ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of (Owner of Casting_Unit)) Equal to True)))) and do (Actions)
            • Loop - Actions
              • -------- The array of the Unit group will be the same as the spell's level in order to keep track of how much the explosion damage will be. --------
              • -------- - --------
              • Unit Group - Add (Picked unit) to Unit_Group_Bounty_Scan[Spell_Level]
        • Else - Actions
      • -------- - --------
      • -------- Clean-up --------
      • -------- - --------
      • Set Casting_Unit = No unit
      • Set Spell_Level = 0
      • Set Spell_Aoe = 0
      • Set Damage_Primary = 0
      • Set Damage_Secondary = 0
      • Custom script: call RemoveLocation(udg_Loc[1])

Trigger no.2
-Removes the unit from the unit group when he doesn't have the specific buffs.

  • Bounty unit Group
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Unit_Group_Bounty_Scan[1] is empty) Equal to False
          • (Unit_Group_Bounty_Scan[2] is empty) Equal to False
          • (Unit_Group_Bounty_Scan[3] is empty) Equal to False
          • (Unit_Group_Bounty_Scan[4] is empty) Equal to False
          • (Unit_Group_Bounty_Scan[5] is empty) Equal to False
    • Actions
      • -------- - --------
      • -------- Pick every unit and check if they have buff or are dead. --------
      • -------- - --------
      • For each (Integer A) from 1 to 5, do (Actions)
        • Loop - Actions
          • Unit Group - Pick every unit in Unit_Group_Bounty_Scan[(Integer A)] and do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • ((Picked unit) has buff Hellfire ) Equal to False
                      • ((Picked unit) has buff Bounty Scan ) Equal to False
                      • ((Picked unit) has buff Bounty ) Equal to False
                • Then - Actions
                  • -------- Remove AoE damage upon death. --------
                  • -------- - --------
                  • Unit Group - Remove (Picked unit) from Unit_Group_Bounty_Scan[(Integer A)]
                  • -------- - --------
                  • -------- SPX --------
                  • -------- - --------
                  • Special Effect - Create a special effect at (Position of (Picked unit)) using Abilities\Spells\Human\DispelMagic\DispelMagicTarget.mdl
                  • Special Effect - Destroy (Last created special effect)
                • Else - Actions
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Yep, found it. When you damage Target_Unit it will cause "Unit in Unit Group Dies" to interrupt your trigger, which will overwrite the variables Casting_Unit, Loc[1], and Damage_Primary. While overwriting Damage_Primary doesn't matter, overwriting Casting_Unit means from then on (Triggering Unit) will refer to the unit that died rather than the unit that casted the ability, and Loc[1] will be in the centre of the map (since you destroyed it) and also obviously leak since the initial one will never be destroyed. The solution to this would be to use a different index of Loc in the "Unit in Unit Group Dies" and to refer to (Triggering Unit) directly rather than storing it in a global variable.

Confusing stuff, I know, but you have to keep in mind that if a trigger causes something to happen that would fire another trigger's event, the second trigger will interrupt execution of the first trigger (much like a function call) rather than waiting for it to finish, and the first trigger will only resume execution after the second is finished.
 
Level 2
Joined
Oct 13, 2010
Messages
9
Wow, didn't realize that the triggers could operate with each other in that way. I've always thought that one trigger made all its actions before next trigger kicks in if you don't have any wait actions.
But it makes some sense and like you said, pretty confusing stuff going on right there. Have to stop using too many global variables I guess. :cwink: But, the trigger works now, thanks a lot, you've been very helpful! :ah:
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
I'll take this opportunity to plug JASS. You should work towards learning it if you have the time; it's much nicer, gives you some better programming experience (both for modding future games and if you are interested in actual standalone programming), isn't that hard, and you seem to be the type of person who'd be able to.

Also, while global variables are indeed awful for most circumstances (here included), this weird trigger behaviour can affect a lot more than just that. I've had a huge amount of trouble with damage detection systems specifically to do with this behaviour.
 

Cokemonkey11

Spell Reviewer
Level 29
Joined
May 9, 2006
Messages
3,534
I'll take this opportunity to plug JASS. You should work towards learning it if you have the time; it's much nicer, gives you some better programming experience (both for modding future games and if you are interested in actual standalone programming), isn't that hard, and you seem to be the type of person who'd be able to.

Also, while global variables are indeed awful for most circumstances (here included), this weird trigger behaviour can affect a lot more than just that. I've had a huge amount of trouble with damage detection systems specifically to do with this behaviour.

Not to mention how much incredibly faster it is to script a decent map in jass by comparison to GUI.
 
Level 2
Joined
Oct 13, 2010
Messages
9
Hm, I don't know if I want to work with JASS really... Always felt that it will be so much harder to keep track on what you are actually doing with JASS. I mean, you're basically looking at a wall of text. Isn't it... confusing? But I gotta say though, the things I heard you could do with JASS makes it pretty tempting though, will probably give it a try.

But... wait, why would it go faster to script a map with JASS? You do have to write the entire trigger, don't you?
(Okay, this is bit Off-topic and I should probably just go and look these things up, but since you have experience with JASS... :cwink:)
 

Cokemonkey11

Spell Reviewer
Level 29
Joined
May 9, 2006
Messages
3,534
It's just a bit different. Now that I've gotten used to jass, I find it difficult to read GUI.

Yes you have to script triggers from scratch, but once you learn how to write the basic structure, everything flows easier.

JASS is much more organized and you can do more in fewer lines too.

And what I mean by faster is that, I can type an action line faster than I can click it in the GUI editor.
 
Level 2
Joined
Oct 13, 2010
Messages
9
Well, if it's just a matter of experience and JASS is more effective, then I guess that there's no reason for me to stick to GUI. So I'm just going to read basics right away in the tutorial section :csmile:
 
Status
Not open for further replies.
Top