• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[Spell] Quill Spray "Each stack has its own duration"

Status
Not open for further replies.
Level 12
Joined
May 16, 2020
Messages
660
Hi all,

I already posted a similar question about Warpath.
This time it's about Quill Spray though, which seems to be even more difficult...

The description from the Dota 2 wiki (Bristleback):
Sprays enemy units with quills dealing damage in an area of effect around Bristleback. Deals bonus damage for every time a unit was hit by Quill Spray in the last 14 seconds.

Whereas Warpath could be done by tracking a Timer (with custom value) for the caster only, here one needs to also tie the stacks to the caster(s) AND target(s).

@Devalut once created this trigger for me, but I realized that the stacks are meant to be independent of each other, i.e. if you hit an enemy, you don't reset the full stack, just add 1 stack for 14 seconds.

  • QuillSpray Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set VariableSet QuillSpray_Config_Damage[1] = 20.00
      • Set VariableSet QuillSpray_Config_Damage[2] = 40.00
      • Set VariableSet QuillSpray_Config_Damage[3] = 60.00
      • Set VariableSet QuillSpray_Config_Damage[4] = 80.00
      • -------- --------
      • Set VariableSet QuillSpray_Config_Damage_Max[1] = 550.00
      • Set VariableSet QuillSpray_Config_Damage_Max[2] = 550.00
      • Set VariableSet QuillSpray_Config_Damage_Max[3] = 550.00
      • Set VariableSet QuillSpray_Config_Damage_Max[4] = 550.00
      • -------- --------
      • Set VariableSet QuillSpray_Config_Damage_Stack[1] = 30.00
      • Set VariableSet QuillSpray_Config_Damage_Stack[2] = 32.00
      • Set VariableSet QuillSpray_Config_Damage_Stack[3] = 34.00
      • Set VariableSet QuillSpray_Config_Damage_Stack[4] = 36.00
  • QuillSpray
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Quill Spray
    • Actions
      • Set VariableSet QuillSpray_Unit = (Triggering unit)
      • Set VariableSet QuillSpray_Point[1] = (Position of QuillSpray_Unit)
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within 700.00 of QuillSpray_Point[1].) and do (Actions)
        • Loop - Actions
          • Set VariableSet QuillSpray_UnitTemp = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (QuillSpray_UnitTemp is alive) Equal to True
              • (QuillSpray_UnitTemp belongs to an enemy of (Owner of QuillSpray_Unit).) Equal to True
              • (QuillSpray_UnitTemp is A structure) Equal to False
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (QuillSpray_UnitTemp is in QuillSpray_Group.) Equal to False
                • Then - Actions
                  • Unit Group - Add QuillSpray_UnitTemp to QuillSpray_Group
                  • Set VariableSet QuillSpray_Index = (QuillSpray_Index + 1)
                  • Set VariableSet QuillSpray_Stack[QuillSpray_Index] = 0
                  • Set VariableSet QuillSpray_Level[QuillSpray_Index] = (Level of Quill Spray for QuillSpray_Unit)
                  • Set VariableSet QuillSpray_Target[QuillSpray_Index] = QuillSpray_UnitTemp
                  • Set VariableSet QuillSpray_Caster[QuillSpray_Index] = QuillSpray_Unit
                  • Set VariableSet QuillSpray_Duration[QuillSpray_Index] = 14.00
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • QuillSpray_Index Equal to 1
                    • Then - Actions
                      • Trigger - Turn on QuillSpray Periodic <gen>
                    • Else - Actions
                • Else - Actions
              • Unit Group - Add QuillSpray_UnitTemp to QuillSpray_Group_Damage
            • Else - Actions
      • Custom script: call RemoveLocation(udg_QuillSpray_Point[1])
  • QuillSpray Periodic
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • For each (Integer QuillSpray_Integer) from 1 to QuillSpray_Index, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (QuillSpray_Target[QuillSpray_Integer] is alive) Equal to True
              • QuillSpray_Duration[QuillSpray_Integer] Greater than 0.00
            • Then - Actions
              • Set VariableSet QuillSpray_Duration[QuillSpray_Integer] = (QuillSpray_Duration[QuillSpray_Integer] - 0.05)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (QuillSpray_Target[QuillSpray_Integer] is in QuillSpray_Group_Damage.) Equal to True
                • Then - Actions
                  • Set VariableSet QuillSpray_Stack[QuillSpray_Integer] = (QuillSpray_Stack[QuillSpray_Integer] + 1)
                  • Set VariableSet QuillSpray_Duration[QuillSpray_Integer] = 14.00
                  • Set VariableSet NextDamageType = DamageTypeSpell
                  • Unit - Cause QuillSpray_Caster[QuillSpray_Integer] to damage QuillSpray_Target[QuillSpray_Integer], dealing (Min((QuillSpray_Config_Damage[QuillSpray_Level[QuillSpray_Integer]] + (QuillSpray_Config_Damage_Stack[QuillSpray_Level[QuillSpray_Integer]] x (Real((QuillSpray_Stack[QuillSpray_Integer] - 1))))), QuillSpray_Config_Damage_Max[QuillSpray_Level[QuillSpray_Integ damage of attack type Normal and damage type Normal
                  • Unit Group - Remove QuillSpray_Target[QuillSpray_Integer] from QuillSpray_Group_Damage.
                • Else - Actions
            • Else - Actions
              • Unit Group - Remove QuillSpray_Target[QuillSpray_Integer] from QuillSpray_Group.
              • Special Effect - Create a special effect attached to the chest of QuillSpray_Target[QuillSpray_Integer] using Abilities\Weapons\DemonHunterMissile\DemonHunterMissile.mdl
              • Special Effect - Destroy (Last created special effect)
              • Set VariableSet QuillSpray_Stack[QuillSpray_Integer] = 0
              • Set VariableSet QuillSpray_Stack[QuillSpray_Integer] = QuillSpray_Stack[QuillSpray_Index]
              • Set VariableSet QuillSpray_Level[QuillSpray_Integer] = QuillSpray_Level[QuillSpray_Index]
              • Set VariableSet QuillSpray_Caster[QuillSpray_Integer] = QuillSpray_Caster[QuillSpray_Index]
              • Set VariableSet QuillSpray_Target[QuillSpray_Integer] = QuillSpray_Target[QuillSpray_Index]
              • -------- --------
              • Set VariableSet QuillSpray_Index = (QuillSpray_Index - 1)
              • Set VariableSet QuillSpray_Integer = (QuillSpray_Integer - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • QuillSpray_Index Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions

Could someone please help add the independence between the stacks?

Also, ideally I'd also like to change the code so that it deals damage via Bribes Damage Engine instead of "checking every 0.05 seconds".

Mainly for 2 reason: a) then I can increase the very low 0.05 timer, and b) the base ability is based on Fan of Knives, which is recognizes by Bribe's Damage Engine even at 0 damage. By working with the DamageEventAmount, I can more cleanly use for example SFXs on spell lifesteal whenever the ability is fired (currently it fires twice).

However, If the trigger is adjusted this way, one needs to consider the interaction between "Bristleback" (the ability):

Bristleback takes less damage if hit on the sides or rear. If Bristleback takes 210 damage from the rear, he releases a Quill Spray of the current level.

Again... not exactly sure how to implement all these requirements into one ability.

Many thanks!
 
Level 24
Joined
Jun 26, 2020
Messages
1,855
The main problem for what you asked is here:
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (QuillSpray_UnitTemp is in QuillSpray_Group.) Equal to False
    • Then - Actions
      • Unit Group - Add QuillSpray_UnitTemp to QuillSpray_Group
      • Set VariableSet QuillSpray_Index = (QuillSpray_Index + 1)
      • Set VariableSet QuillSpray_Stack[QuillSpray_Index] = 0
      • Set VariableSet QuillSpray_Level[QuillSpray_Index] = (Level of Quill Spray for QuillSpray_Unit)
      • Set VariableSet QuillSpray_Target[QuillSpray_Index] = QuillSpray_UnitTemp
      • Set VariableSet QuillSpray_Caster[QuillSpray_Index] = QuillSpray_Unit
      • Set VariableSet QuillSpray_Duration[QuillSpray_Index] = 14.00
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • QuillSpray_Index Equal to 1
        • Then - Actions
          • Trigger - Turn on QuillSpray Periodic <gen>
        • Else - Actions
      • Else - Actions
    • Else - Actions
If you wanna make the charges independant from each other you should remove that "(QuillSpray_UnitTemp is in QuillSpray_Group.) Equal to False" condition to create various differents instances to the same target instead of update the same instance on the unit, and doing that you won't need the "QuillSpray_Stack" variable, because it will damage the target as many instances this unit has
Also you can make the base ability do the base damage instead of trigger it.
But of if you wanna have a max damage the thing becomes tricky, the unique thing I can though is having a unit indexer, have a variable that stores the max damage the target must receive, have a unit group that stores the affected units and loop it at the top of the timer trigger and substract it everytime the unit is damaged, like this:
  • QuillSpray Periodic
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in Targets and do (Actions)
        • Loop - Actions
          • Set VariableSet Max_Damage[(Custom value of (Picked Unit))] = 550.00
      • For each (Integer QuillSpray_Integer) from 1 to QuillSpray_Index, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (QuillSpray_Target[QuillSpray_Integer] is alive) Equal to True
              • QuillSpray_Duration[QuillSpray_Integer] Greater than 0.00
            • Then - Actions
              • Set TempInt = (Custom value of QuillSpray_Target[QuillSpray_Integer])
              • Unit - Cause QuillSpray_Caster[QuillSpray_Integer] to damage QuillSpray_Target[QuillSpray_Integer], dealing (Min(QuillSpray_Config_Damage_Stack[QuillSpray_Integer], Max_Damage[TempInt])) damage of attack type Normal and damage type Normal
              • Set VariableSet Max_Damage[TempInt] = Max_Damage[TempInt] - QuillSpray_Stack[QuillSpray_Integer]
            • Else - Actions
 

Uncle

Warcraft Moderator
Level 66
Joined
Aug 10, 2018
Messages
6,727
For the passive proc that triggers after X damage is taken, you can make a Dummy unit cast the fan of knives ability and link the dummy to the hero. Then using the Damage Engine, catch when this dummy deals damage, get it's linked hero, set the damage dealt to 0 and have the linked hero deal the damage instead.

Is it essential that you design these spells to work for multiple Bristlebacks at a time?
 
Level 12
Joined
May 16, 2020
Messages
660
Man this spell is really giving me headaches.

I realized that the above trigger increases the stacks even when two different casters damage an enemy. So to make the spell truly MUI, I tried adding an additional condition on the stacks for each caster.

But currently nothing seems to work... would you mind looking at this Uncle please?

  • Quill Spray Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Quill Spray
    • Actions
      • Set VariableSet AA_Index_A = (AA_Index_A + 1)
      • Set VariableSet AA_Caster[AA_Index_A] = (Triggering unit)
      • Set VariableSet AA_Duration[AA_Index_A] = 28
      • -------- --------
      • Set VariableSet AA_CV = (Custom value of AA_Caster[AA_Index_A])
      • Custom script: set udg_AA_Group[udg_AA_CV] = CreateGroup()
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • AA_Index_A Equal to 1
        • Then - Actions
          • Game - Display to (All players) the text: ON
          • Countdown Timer - Start AA_Timer as a Repeating timer that will expire in 0.50 seconds
          • Trigger - Turn on Quill Spray Damage <gen>
          • Trigger - Turn on Quill Spray Loop <gen>
        • Else - Actions
  • Quill Spray Damage
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
      • (Level of Quill Spray for DamageEventSource) Greater than 0
      • DamageEventDamageT Equal to DAMAGE_TYPE_ENHANCED
    • Actions
      • Set VariableSet AA_CV = (Custom value of DamageEventSource)
      • -------- --------
      • Custom script: set udg_AA_HandleID_Caster = GetHandleId(udg_DamageEventSource)
      • Custom script: set udg_AA_HandleID_Target = GetHandleId(udg_DamageEventTarget)
      • -------- --------
      • -------- CREATE NEW GROUP TO TIE STACKS TO TARGET [I]AND[/I] CASTER --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (DamageEventTarget is in AA_Group[AA_CV].) Equal to False
        • Then - Actions
          • Game - Display to (All players) the text: Added to Caster's G...
          • Unit Group - Add DamageEventTarget to AA_Group[AA_CV]
          • -------- --------
          • Set VariableSet AA_Index_B = (AA_Index_B + 1)
          • -------- --------
          • -------- DEFINE DURATION OF THIS NEW STACK --------
          • Set VariableSet AA_Duration_HS = 28
          • Hashtable - Save AA_Duration_HS as AA_HandleID_Caster of AA_Index_B in AA_Hashtable.
          • -------- --------
          • -------- INITIATE STACK AMOUNT --------
          • Set VariableSet AA_Stack_HS = 0
          • Hashtable - Save AA_Stack_HS as AA_HandleID_Caster of AA_HandleID_Target in AA_Hashtable.
          • -------- --------
          • -------- ADD UNDISPELLABLE DEBUFF --------
          • -------- --------
          • Game - Display to (All players) the text: (String(AA_Stack_HS))
          • Game - Display to (All players) the text: (String(AA_Duration_HS))
        • Else - Actions
          • Game - Display to (All players) the text: Already in Caster's...
          • -------- --------
          • Set VariableSet AA_Index_B = (AA_Index_B + 1)
          • -------- --------
          • -------- DEFINE DURATION OF THIS NEW STACK --------
          • Set VariableSet AA_Duration_HS = 28
          • Hashtable - Save AA_Duration_HS as AA_HandleID_Caster of AA_Index_B in AA_Hashtable.
          • -------- --------
          • -------- ADJUST STACK AMOUNT --------
          • Set VariableSet AA_Stack_HS = (Load AA_HandleID_Caster of AA_HandleID_Target from AA_Hashtable.)
          • Set VariableSet AA_Stack_HS = (AA_Stack_HS + 1)
          • Hashtable - Save AA_Stack_HS as AA_HandleID_Caster of AA_HandleID_Target in AA_Hashtable.
          • -------- --------
          • Game - Display to (All players) the text: (String(AA_Stack_HS))
      • -------- --------
      • -------- --------
      • -------- DAMAGE TARGET --------
      • Set VariableSet AA_Level = (Level of Quill Spray for DamageEventSource)
      • Set VariableSet DamageEventType = DamageTypeSpell
      • Set VariableSet DamageEventAmount = (DamageEventAmount + (QuillSpray_Config_Damage_Stack[AA_Level] x (Real(AA_Stack_HS))))
  • Quill Spray Loop
    • Events
      • Time - AA_Timer expires
    • Conditions
    • Actions
      • For each (Integer AA_Integer_A) from 1 to AA_Index_A, do (Actions)
        • Loop - Actions
          • Set VariableSet AA_Duration[AA_Integer_A] = (AA_Duration[AA_Integer_A] - 1)
          • Set VariableSet AA_CV = (Custom value of AA_Caster[AA_Integer_A])
          • Custom script: set udg_AA_HandleID_Caster = GetHandleId(udg_AA_Caster[udg_AA_Integer_A])
          • Game - Display to (All players) the text: (String((Number of units in AA_Group[AA_CV])))
          • Unit Group - Pick every unit in AA_Group[AA_CV] and do (Actions)
            • Loop - Actions
              • Set VariableSet AA_Target = (Picked unit)
              • Custom script: set udg_AA_HandleID_Target = GetHandleId(udg_AA_Target)
              • -------- --------
              • For each (Integer AA_Integer_B) from 1 to AA_Index_B, do (Actions)
                • Loop - Actions
                  • Set VariableSet AA_Duration_HS = (Load AA_HandleID_Caster of AA_Integer_B from AA_Hashtable.)
                  • Set VariableSet AA_Duration_HS = (AA_Duration_HS - 1)
                  • Hashtable - Save AA_Duration_HS as AA_HandleID_Caster of AA_Integer_B in AA_Hashtable.
                  • Game - Display to (All players) the text: (String(AA_Duration_HS))
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • AA_Duration_HS Equal to 0
                    • Then - Actions
                      • Set VariableSet AA_Stack_HS = (Load AA_HandleID_Caster of AA_HandleID_Target from AA_Hashtable.)
                      • Set VariableSet AA_Stack_HS = (AA_Stack_HS - 1)
                      • Hashtable - Save AA_Stack_HS as AA_HandleID_Caster of AA_HandleID_Target in AA_Hashtable.
                      • Game - Display to (All players) the text: Stack reduced...
                      • -------- --------
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • AA_Stack_HS Equal to 0
                        • Then - Actions
                          • Game - Display to (All players) the text: Removed target from...
                          • Unit Group - Remove AA_Target from AA_Group_HS.
                          • Hashtable - Clear all child hashtables of child AA_HandleID_Caster in AA_Hashtable.
                        • Else - Actions
                    • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AA_Duration[AA_Integer_A] Equal to 0
              • (AA_Group_HS is empty) Equal to True
            • Then - Actions
              • Set VariableSet AA_Caster[AA_Integer_A] = AA_Caster[AA_Index_A]
              • Set VariableSet AA_Duration[AA_Integer_A] = AA_Duration[AA_Index_A]
              • -------- --------
              • Set VariableSet AA_Index_A = (AA_Index_A - 1)
              • Set VariableSet AA_Integer_A = (AA_Integer_A - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • AA_Index_A Equal to 0
                • Then - Actions
                  • Game - Display to (All players) the text: OFF
                  • Countdown Timer - Pause AA_Timer
                  • Trigger - Turn off Quill Spray Damage <gen>
                  • Trigger - Turn off (This trigger)
                • Else - Actions
            • Else - Actions

Also, if the above is more or less the right direction, is there a chance that these might overwrite each other?

  • Hashtable - Save AA_Duration_HS as AA_HandleID_Caster of AA_Index_B in AA_Hashtable.
  • Hashtable - Save AA_Stack_HS as AA_HandleID_Caster of AA_HandleID_Target in AA_Hashtable.
 
Level 24
Joined
Feb 9, 2009
Messages
1,787
If you use Bribe's Unit indexer you can simply increase or decrease a "Stack" variable within a cast or de-index.
  • QuillSpray Cast GUI
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to QuSp_Config_Ability_ID[1]
    • Actions
      • Set VariableSet QuSp_A_Unit = (Triggering unit)
      • Set VariableSet QuSp_A_Point[1] = (Position of QuSp_A_Unit)
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within QuSp_Config_AOE[(Level of QuSp_Config_Ability_ID[1] for QuSp_A_Unit)] of QuSp_A_Point[1].) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Life of (Picked unit)) Greater than 0.40
              • ((Picked unit) belongs to an enemy of (Owner of (QuSp_A_Unit)).) Equal to True
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • QuSp_A_Index Equal to 0
                • Then - Actions
                  • Trigger - Turn on QuillSpray Periodic <gen>
                • Else - Actions
              • Set VariableSet QuSp_A_Index = (QuSp_A_Index + 1)
              • Set VariableSet QuSp_B_Level[QuSp_A_Index] = (Level of QuSp_Config_Ability_ID[1] for QuSp_A_Unit)
              • Set VariableSet QuSp_B_Unit[QuSp_A_Index] = (Picked unit)
              • Set VariableSet QuSp_B_Unit_Caster[QuSp_A_Index] = QuSp_A_Unit
              • Set VariableSet QuSp_B_Timer[QuSp_A_Index] = QuSp_Config_Stack_Duration[QuSp_B_Level[QuSp_A_Index]]
              • Unit - Cause QuSp_B_Unit_Caster[QuSp_A_Index] to damage QuSp_B_Unit[QuSp_A_Index], dealing (QuSp_Config_Damage[QuSp_B_Level[QuSp_A_Index]] + (QuSp_Config_Damage_Stack[QuSp_B_Level[QuSp_A_Index]] x (Real(QuSp_B_Stack[(Custom value of (Picked unit))])))) damage of attack type Spells and damage type Normal
              • Set VariableSet QuSp_B_Stack[(Custom value of (Picked unit))] = (QuSp_B_Stack[(Custom value of (Picked unit))] + 1)
            • Else - Actions
      • Custom script: call RemoveLocation(udg_QuSp_A_Point[1])
  • QuillSpray Periodic
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • For each (Integer QuSp_A_Loop) from 1 to QuSp_A_Index, 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
                  • (Life of QuSp_B_Unit[QuSp_A_Loop]) Greater than 0.40
                  • QuSp_B_Timer[QuSp_A_Loop] Greater than 0.00
            • Then - Actions
              • Set VariableSet QuSp_B_Timer[QuSp_A_Loop] = (QuSp_B_Timer[QuSp_A_Loop] - 0.05)
            • Else - Actions
              • Set VariableSet QuSp_B_Stack[(Custom value of QuSp_B_Unit[QuSp_A_Loop])] = (QuSp_B_Stack[(Custom value of QuSp_B_Unit[QuSp_A_Loop])] - 1)
              • Set VariableSet QuSp_B_Level[QuSp_A_Loop] = QuSp_B_Level[QuSp_A_Index]
              • Set VariableSet QuSp_B_Unit_Caster[QuSp_A_Loop] = QuSp_B_Unit_Caster[QuSp_A_Index]
              • Set VariableSet QuSp_B_Unit[QuSp_A_Loop] = QuSp_B_Unit[QuSp_A_Index]
              • Set VariableSet QuSp_B_Timer[QuSp_A_Loop] = QuSp_B_Timer[QuSp_A_Index]
              • Set VariableSet QuSp_A_Index = (QuSp_A_Index - 1)
              • Set VariableSet QuSp_A_Loop = (QuSp_A_Loop - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • QuSp_A_Index Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
 
Last edited:
Level 24
Joined
Jun 26, 2020
Messages
1,855
@Ugabunda Ay, if your map gonna have more than one caster with that ability you would have said it, because what I said was thinking there was only 1 caster at time.
To solve this is a little tricky, but to start: why do you have a loop inside the Unit Group Loop? in the timer trigger, with the Unit Group Loop is enough.
 
Level 12
Joined
May 16, 2020
Messages
660
Thanks guys. Took a small break to look at this with fresh eyes, but still failing to progress.

@Devalut : As Herly wrote below, the problem with this is if you have several casters in the map. If both casters belong to the same team, they would would increase the stack amount on the same enemy.

@HerlySQR : The loop in the group was just to experiment. I know this won't go anywhere...

Would anyone have a smart idea how to do this?
I truly don't see an "easy" way, not even with a hashtable. It seems like too much information needs to be stored within limited slots.
 
Level 24
Joined
Jun 26, 2020
Messages
1,855
@Ugabunda I think you will need a triple array, because any caster needs a double array, if your map don't have any trigger converted to custom script or a custom script actived, you can turn it to Lua so you can use its tables those they can have any array size (while it doesn't exceeds the 32-bits limit).

If you can't do that, you have to be more tricky to emulate a triple array with a double array.
 
Level 24
Joined
Jun 26, 2020
Messages
1,855
I noticed something (if you don't edited the last triggers you posted).
  • Set VariableSet AA_CV = (Custom value of AA_Caster[AA_Index_A])
  • Custom script: set udg_AA_Group[udg_AA_CV] = CreateGroup()
You are creating a group everytime the caster casts the spell and overwriting it, you should add:
  • Set VariableSet AA_CV = (Custom value of AA_Caster[AA_Index_A])
  • Custom script: if udg_AA_Group[udg_AA_CV] == null then
  • Custom script: set udg_AA_Group[udg_AA_CV] = CreateGroup()
  • Custom script: endif
And when the spell ends you should add:
  • Set VariableSet AA_CV = (Custom value of AA_Caster[AA_Index_A])
  • Custom script: call DestroyGroup(udg_AA_Group[udg_AA_CV])
  • Custom script: set udg_AA_Group[udg_AA_CV] = null
Edit: Thinking well I think there are more to consider, let me try.
Edit 2:

Starting from 0:

1) Better instead of create the instances of the caster when he cast the spell, better instead create it when he damages like this:
  • Quill Spray Damage
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
      • (Level of Quill Spray for DamageEventSource) Greater than 0
      • DamageEventDamageT Equal to DAMAGE_TYPE_ENHANCED
    • Actions
      • Set VariableSet AA_CV = (Custom value of DamageEventSource)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • AA_Instanced[AA_CV] Equal to False
        • Then - Actions
          • Set VariableSet AA_Instanced[AA_CV] = True
          • Set VariableSet AA_Index_A = (AA_Index_A + 1)
          • Set VariableSet AA_Caster[AA_Index_A] = DamageEventSource
          • Set VariableSet AA_Duration[AA_Index_A] = 28
          • -------- --------
          • Custom script: set udg_AA_Group[AA_CV] = CreateGroup()
          • -------- --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AA_Index_A Equal to 1
            • Then - Actions
              • Game - Display to (All players) the text: ON
              • Countdown Timer - Start AA_Timer as a Repeating timer that will expire in 0.50 seconds
              • Trigger - Turn on Quill Spray Damage <gen>
              • Trigger - Turn on Quill Spray Loop <gen>
            • Else - Actions
2) If you are using a unit indexer you dont need use the HandleId of the target or the caster
3) For what you want (MUI and every stack is independant) as I said you need a triple array basically something like:

"Duration[CasterId][TargetId][StackId]"

, and as you don't wanna pass to Lua, so you should emulate it with 2 indexes, to do that you should know what can be the max. value of some of this indexes, like if the max number of stacks can have every target from an specific caster is 10, to store its duration you should do (obviously with the hashtable, but I will use an array only to show):

Duration[CasterId][TargetId*10+StackId] = "Your value"

If you know how many units can be in a map (A limit to the unit indexer) and the value is something like 1000 instead you can do:

Duration[CasterId][StackId*1000+TargetId] = "Your value"


These are just suggestions to give you an idea.
 
Last edited:
Level 12
Joined
May 16, 2020
Messages
660
Sorry Herly for not replying sooner. I keep trying every once and then with a fresh mind, but even with the tips I'm not making progress.

@Uncle / @HerlySQR : If you have the time, would you mind showing how you would do it in a testmap?
Ideally with something that can also be used with Bristleback (the ability). This is another condition in the entire set-up which makes it even more complicated.

Bristleback takes less damage if hit on the sides or rear. If Bristleback takes 210 damage from the rear, he releases a Quill Spray of the current level.
Rear Angle: 70°
Side Angle: 110°
Rear Damage Reduction: 16%/24%/32%/40%
Side Damage Reduction: 8%/12%/16%/20%
Damage Threshold: 210

Devalut created the following trigger, which can be perfectly used for the back/side damage reduction:

  • Bristleback Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set VariableSet Bristleback_Reduc_Side[1] = 0.08
      • Set VariableSet Bristleback_Reduc_Side[2] = 0.12
      • Set VariableSet Bristleback_Reduc_Side[3] = 0.16
      • Set VariableSet Bristleback_Reduc_Side[4] = 0.20
      • -------- --------
      • Set VariableSet Bristleback_Reduc_Rear[1] = 0.16
      • Set VariableSet Bristleback_Reduc_Rear[2] = 0.24
      • Set VariableSet Bristleback_Reduc_Rear[3] = 0.32
      • Set VariableSet Bristleback_Reduc_Rear[4] = 0.40
  • Bristleback
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
      • (Level of Bristleback for DamageEventTarget) Greater than 0
    • Actions
      • Set VariableSet Bristleback_Point[3] = (Position of DamageEventTarget)
      • Set VariableSet Bristleback_Point[4] = (Position of DamageEventSource)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Acos((Cos(((Angle from Bristleback_Point[4] to Bristleback_Point[3]) - (Facing of DamageEventTarget)))))) Greater than or equal to 70.00
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Acos((Cos(((Angle from Bristleback_Point[4] to Bristleback_Point[3]) - (Facing of DamageEventTarget)))))) Greater than 110.00
            • Then - Actions
            • Else - Actions
              • -------- ATTACKED FROM SIDE --------
              • Set VariableSet DamageEventAmount = (DamageEventAmount x (1.00 - Bristleback_Reduc_Side[(Level of Bristleback for DamageEventTarget)]))
        • Else - Actions
          • -------- ATTACKED FROM REAR --------
          • Set VariableSet DamageEventAmount = (DamageEventAmount x (1.00 - Bristleback_Reduc_Rear[(Level of Bristleback for DamageEventTarget)]))
          • -------- REQUIRES QUILL SPRAY ABIILITY --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Level of Quill Spray for DamageEventTarget) Greater than 0
            • Then - Actions
              • For each (Integer Bristleback_Integer) from 1 to Bristleback_Index, do (Actions)
                • Loop - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • DamageEventTarget Equal to Bristleback_Unit[Bristleback_Integer]
                    • Then - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • DamageEventAmount Greater than or equal to Bristleback_Threshold[Bristleback_Integer]
                        • Then - Actions
                          • Set VariableSet Bristleback_Threshold[Bristleback_Integer] = 210.00
                          • Set VariableSet QuillSpray_Unit = DamageEventTarget
                          • Set VariableSet Bristleback_Point[0] = (Position of QuillSpray_Unit)
                          • -------- --------
                          • Unit - Create 1 Dummy (Fly/Speed 0) for (Owner of QuillSpray_Unit) at Bristleback_Point[0] facing Default building facing degrees
                          • Set VariableSet Bristleback_Dummy = (Last created unit)
                          • Unit - Add Quill Spray (Dummy) to Bristleback_Dummy
                          • Unit - Order Bristleback_Dummy to Night Elf Warden - Fan Of Knives.
                          • Unit - Add a 0.50 second Generic expiration timer to Bristleback_Dummy
                          • -------- --------
                          • Custom script: set bj_wantDestroyGroup = true
                          • Unit Group - Pick every unit in (Units within 700.00 of Bristleback_Point[0].) and do (Actions)
                            • Loop - Actions
                              • Set VariableSet Bristleback_UnitTemp = (Picked unit)
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • (Bristleback_UnitTemp is alive) Equal to True
                                  • (Bristleback_UnitTemp belongs to an enemy of (Owner of QuillSpray_Unit).) Equal to True
                                • Then - Actions
                                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    • If - Conditions
                                      • (Bristleback_UnitTemp is in QuillSpray_Group.) Equal to False
                                    • Then - Actions
                                      • Set VariableSet QuillSpray_Index = (QuillSpray_Index + 1)
                                      • Set VariableSet QuillSpray_Stack[QuillSpray_Index] = 0
                                      • Set VariableSet QuillSpray_Level[QuillSpray_Index] = (Level of Quill Spray for QuillSpray_Unit)
                                      • Set VariableSet QuillSpray_Target[QuillSpray_Index] = Bristleback_UnitTemp
                                      • Set VariableSet QuillSpray_Caster[QuillSpray_Index] = QuillSpray_Unit
                                      • Set VariableSet QuillSpray_Duration[QuillSpray_Index] = 14.00
                                      • Unit Group - Add Bristleback_UnitTemp to QuillSpray_Group
                                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                        • If - Conditions
                                          • QuillSpray_Index Equal to 1
                                        • Then - Actions
                                          • Trigger - Turn on QuillSpray Periodic <gen>
                                        • Else - Actions
                                    • Else - Actions
                                  • Unit Group - Add Bristleback_UnitTemp to QuillSpray_Group_Damage
                                • Else - Actions
                          • Custom script: call RemoveLocation(udg_Bristleback_Point[0])
                        • Else - Actions
                          • Set VariableSet Bristleback_Threshold[Bristleback_Integer] = (Bristleback_Threshold[Bristleback_Integer] - (DamageEventAmount x (1.00 - Bristleback_Reduc_Rear[(Level of Bristleback for DamageEventTarget)])))
                      • Custom script: call RemoveLocation(udg_Bristleback_Point[3])
                      • Custom script: call RemoveLocation(udg_Bristleback_Point[4])
                      • Skip remaining actions
                    • Else - Actions
              • Set VariableSet Bristleback_Index = (Bristleback_Index + 1)
              • Set VariableSet Bristleback_Unit[Bristleback_Index] = DamageEventTarget
              • Set VariableSet Bristleback_Threshold[Bristleback_Index] = 210.00
            • Else - Actions
      • Custom script: call RemoveLocation(udg_Bristleback_Point[3])
      • Custom script: call RemoveLocation(udg_Bristleback_Point[4])
 
Status
Not open for further replies.
Top