• 🏆 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] Why doesn't this channeling deal damage every second?

Level 8
Joined
Jun 11, 2018
Messages
102
What am I doing wrong? The spell deals damage on the first cast, but not on the if/then/else.

  • Wrap
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Ability being cast) Equal to Wrap E
          • (Ability being cast) Equal to Wrap Q
          • (Ability being cast) Equal to Wrap R
          • (Ability being cast) Equal to Wrap W
    • Actions
      • Unit - Cause (Casting unit) to damage (Target unit of ability being cast), dealing (15.00 + (Real((Strength of (Casting unit) (Include bonuses))))) damage of attack type Normal and damage type Normal
      • Wait 1.00 seconds
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Current order of Ekans 0145 <gen>) Equal to (Order((Order(magicleash)))
        • Then - Actions
          • Unit - Cause (Casting unit) to damage (Target unit of ability being cast), dealing (15.00 + (Real((Strength of (Casting unit) (Include bonuses))))) damage of attack type Normal and damage type Normal
          • Wait 1.00 seconds
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Current order of Ekans 0145 <gen>) Equal to (Order((Order(magicleash)))
            • Then - Actions
              • Unit - Cause (Casting unit) to damage (Target unit of ability being cast), dealing (15.00 + (Real((Strength of (Casting unit) (Include bonuses))))) damage of attack type Normal and damage type Normal
              • Wait 1.00 seconds
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Current order of Ekans 0145 <gen>) Equal to (Order((Order(magicleash)))
                • Then - Actions
                  • Unit - Cause (Casting unit) to damage (Target unit of ability being cast), dealing (15.00 + (Real((Strength of (Casting unit) (Include bonuses))))) damage of attack type Normal and damage type Normal
                  • Wait 1.00 seconds
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Current order of Ekans 0145 <gen>) Equal to (Order((Order(magicleash)))
                    • Then - Actions
                      • Unit - Cause (Casting unit) to damage (Target unit of ability being cast), dealing (15.00 + (Real((Strength of (Casting unit) (Include bonuses))))) damage of attack type Normal and damage type Normal
                      • Wait 1.00 seconds
                    • Else - Actions
                • Else - Actions
            • Else - Actions
        • Else - Actions
 
Level 39
Joined
Feb 27, 2007
Messages
5,016
  • Target Unit of Ability Being Cast is not usable after a wait, where it will return null.
  • Casting Unit has a similar issue in that after a wait it will refer to whatever unit in the map has most recently cast a spell. Triggering Unit never has this issue and should always be used instead of the more specific event responses if at all possible.
  • You have hardcoded in the order check to refer to a specific instance of the Ekans unit (Ekans 0145). This is obviously means Wrap won't ever work for any other Ekans. I don't have a recommendation for how to fix this because I know nothing about how your map is structured or what other systems/code you are using.
  • Generally speaking Waits are bad news and should be avoided whenever possible.
  • Aerial Shackles has a field for Damage Per Second, so why are you not using that instead? It would simplify things significantly. I see you want damage to scale with an attribute, but you can modify ability fields of abilities at runtime now so you could just change it to be the correct damage before the spell is fully cast.
  • Because this spell has 5 damage instances with 4 waits in between technically it doesn't deal (15 + STR) DPS; it does 5/4*(15 + STR) DPS.
  • Events
    • -------- Yes we are using Begins Casting here instead of Starts the Effect --------
    • -------- That's because we want this to happen before the cast actually occurs so we can modify the damage dealt --------
    • -------- It doesn't matter if the player cancels and re-casts the spell repeatedly; no errant behavior will occur --------
    • Unit - A unit begins casting an ability
  • Conditions
    • Or - Any conditions are true
      • Conditions
        • (Ability being cast) equal to Wrap Q
        • (Ability being cast) equal to Wrap W
        • (Ability being cast) equal to Wrap E
        • (Ability being cast) equal to Wrap R
  • Actions
    • Set NewDPS = (15.00 + (Real((Strength of (Triggering unit) (Include bonuses)))))
    • Set NewDPS = ((5.00 / 4.00) x NewDPS)
    • Ability - Set Ability: (Unit: (Triggering unit)'s Ability with Ability Code: (Ability being cast))'s Real Level Field: Damage Per Second ('mls1') of Level: ((Level of (Ability being cast) for (Triggering unit)) - 1) to NewDPS
  • The line that allows you to modify the ability fields is very important. Note that it uses Ability Being Cast because there are 4 different Wrap spells.
  • It also must use the correct field (in this case 'mls1'). There are many fields called "damage over time" but the rawcode of the field must be the correct one. You can see the field IDs in the object editor by pressing ctrl+D
  • Since Damage over Time is a field that would scale with level (if the spell has levels, which I don't know) it won't be found in the Ability Real Field menu but in the Ability Real Level Field menu.
  • Most (but not all) of the ability fields are 0-indexed, meaning that level 1 uses index 0 (and level 6 would use index 5, etc.); I've baked this in with a level - 1 bit here, but it may be that that field is a 1-indexed field and you'll have to remove that -1.
  • This will not affect the damage output of any other Ekans on the map; only this specific instance of this ability.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,552
Pyro beat me to the punch.

But here's something useful as well, a proper way to trigger a spell like this using a method calling dynamic indexing.
  • Wrap Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Wrap
    • Actions
      • Set VariableSet Wrap_Index = (Wrap_Index + 1)
      • Set VariableSet Wrap_Caster[Wrap_Index] = (Triggering unit)
      • Set VariableSet Wrap_Target[Wrap_Index] = (Target unit of ability being cast)
      • Set VariableSet Wrap_Damage[Wrap_Index] = (15.00 + ((Real((Strength of Wrap_Caster[Wrap_Index] (Include bonuses)))) x 1.00))
      • Set VariableSet Wrap_Interval[Wrap_Loop] = 1.00
      • -------- --------
      • -------- Turn on if it's not already on: --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Wrap_Index Equal to 1
        • Then - Actions
          • Trigger - Turn on Wrap Loop <gen>
        • Else - Actions
  • Wrap Stop
    • Events
      • Unit - A unit Stops casting an ability
    • Conditions
      • (Ability being cast) Equal to Wrap
    • Actions
      • -------- Keep track of the unit that stopped casting wrap: --------
      • Set VariableSet Wrap_Caster[0] = (Triggering unit)
      • -------- --------
      • For each (Integer Wrap_Loop) from 1 to Wrap_Index, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Wrap_Caster[0] Equal to Wrap_Caster[Wrap_Loop]
              • Wrap_Caster[0] Not equal to No unit
            • Then - Actions
              • -------- Just a safety measure to make sure this only happens once: --------
              • Set VariableSet Wrap_Caster[0] = No unit
              • -------- --------
              • -------- Restructure the array to remove this instance from it: --------
              • Set VariableSet Wrap_Caster[Wrap_Loop] = Wrap_Caster[Wrap_Index]
              • Set VariableSet Wrap_Target[Wrap_Loop] = Wrap_Target[Wrap_Index]
              • Set VariableSet Wrap_Damage[Wrap_Loop] = Wrap_Damage[Wrap_Index]
              • Set VariableSet Wrap_Interval[Wrap_Loop] = Wrap_Interval[Wrap_Index]
              • -------- --------
              • -------- Reduce the size of the array and set the loop back a cycle: --------
              • Set VariableSet Wrap_Loop = (Wrap_Loop - 1)
              • Set VariableSet Wrap_Index = (Wrap_Index - 1)
              • -------- --------
              • -------- Turn off if all instances are finished: --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Wrap_Index Equal to 0
                • Then - Actions
                  • Trigger - Turn off Wrap Loop <gen>
                • Else - Actions
            • Else - Actions
  • Wrap Loop
    • Events
      • Time - Every 0.02 seconds of game time
    • Conditions
    • Actions
      • For each (Integer Wrap_Loop) from 1 to Wrap_Index, do (Actions)
        • Loop - Actions
          • -------- Keep track of how much time has passed: --------
          • Set VariableSet Wrap_Interval[Wrap_Loop] = (Wrap_Interval[Wrap_Loop] - 0.02)
          • -------- --------
          • -------- If 1.00 second has passed then deal damage and reset the interval: --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Wrap_Interval[Wrap_Loop] Less than or equal to 0.01
            • Then - Actions
              • -------- Reset the interval: --------
              • Set VariableSet Wrap_Interval[Wrap_Loop] = 1.00
              • -------- --------
              • -------- Deal the damage: --------
              • Unit - Cause Wrap_Caster[Wrap_Loop] to damage Wrap_Target[Wrap_Loop], dealing Wrap_Damage[Wrap_Loop] damage of attack type Normal and damage type Normal
            • Else - Actions
It's not too complicated once you get the hang of it. The thread I linked explains it very well.
 

Attachments

  • Wrap Example 1.w3m
    20.2 KB · Views: 0
Last edited:
Top