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

Phoenix Wave v1

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
Hello, this is my first spell that I've decided to upload so, if you have any comments about my triggering or about the spell, please don't hesitate to say it.

Spell Description (might be different from the one in the map): Sends a devastating Phoenix ravaging enemy units it encounters. Once it reaches its target, it will drag it 375 units away before turning around and dragging it back towards the caster. Once it reaches the caster, the Phoenix explodes, dealing 300 damage to a 300 AoE around it. As the Phoenix travels, it knocks away any other enemy unit it encounters and causing them to take 25 damage per second for 25 seconds.

I've tested this spell and so far, its:
MUI
Leakless and
Lagless

Here are the triggers:

Initialization
  • Phoenix Wave Start
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Phoenix Wave
    • Actions
      • Set PW_Integer_Count = (PW_Integer_Count + 1)
      • Set PW_Integer_Max = (PW_Integer_Max + 1)
      • -------- CONFIGURABLES --------
      • -------- The distance the target unit is dragged when the Phoenix reaches it: --------
      • Set PW_Real_DragDistance[PW_Integer_Count] = 375.00
      • -------- The damage dealt when the Phoenix explodes: --------
      • Set PW_Real_Dmg[PW_Integer_Count] = 300.00
      • -------- The AoE of which the explosion damage is dealt: --------
      • Set PW_Real_AoE[PW_Integer_Count] = 300.00
      • -------- The AoE of which the knockback detects enemies: --------
      • Set PW_Real_KBAoE[PW_Integer_Count] = 250.00
      • -------- The speed of the Phoenix per second: --------
      • Set PW_Real_Speed[PW_Integer_Count] = 1200.00
      • -------- The return distance from the caster: --------
      • Set PW_Real_ReturnDst[PW_Integer_Count] = 150.00
      • -------- CONFIGURABLES END --------
      • Set PW_Unit_Caster[PW_Integer_Count] = (Triggering unit)
      • Set PW_Unit_Target[PW_Integer_Count] = (Target unit of ability being cast)
      • Set PW_Point_CasterLoc = (Position of PW_Unit_Caster[PW_Integer_Count])
      • Set PW_Point_TargetLoc = (Position of PW_Unit_Target[PW_Integer_Count])
      • Unit - Create 1 Phoenix Wave Dummy (Phoenix) for (Triggering player) at PW_Point_CasterLoc facing (Angle from PW_Point_CasterLoc to PW_Point_TargetLoc) degrees
      • Set PW_Unit_Dummy[PW_Integer_Count] = (Last created unit)
      • Animation - Change PW_Unit_Dummy[PW_Integer_Count]'s vertex coloring to (100.00%, 100.00%, 100.00%) with 50.00% transparency
      • Set PW_Boolean_DamageDealt[PW_Integer_Count] = False
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Phoenix Wave Loop <gen> is on) Equal to True
        • Then - Actions
        • Else - Actions
          • Trigger - Turn on Phoenix Wave Loop <gen>
      • Custom script: call RemoveLocation(udg_PW_Point_CasterLoc)
      • Custom script: call RemoveLocation(udg_PW_Point_TargetLoc)
Loop
  • Phoenix Wave Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer PW_Integer_Index) from 1 to PW_Integer_Count, do (Actions)
        • Loop - Actions
          • Set PW_Point_DummyLoc = (Position of PW_Unit_Dummy[PW_Integer_Index])
          • Set PW_Point_TargetLoc = (Position of PW_Unit_Target[PW_Integer_Index])
          • Set PW_Real_TrueSpeed = (PW_Real_Speed[PW_Integer_Index] x 0.03)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between PW_Point_DummyLoc and PW_Point_TargetLoc) Greater than PW_Real_TrueSpeed
            • Then - Actions
              • Set PW_Point_OffsetLoc = (PW_Point_DummyLoc offset by PW_Real_TrueSpeed towards (Angle from PW_Point_DummyLoc to PW_Point_TargetLoc) degrees)
              • Unit - Move PW_Unit_Dummy[PW_Integer_Index] instantly to PW_Point_OffsetLoc, facing (Angle from PW_Point_DummyLoc to PW_Point_TargetLoc) degrees
              • Custom script: call RemoveLocation(udg_PW_Point_OffsetLoc)
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • PW_Real_DragDistance[PW_Integer_Index] Greater than 0.00
                • Then - Actions
                  • Unit - Turn collision for PW_Unit_Target[PW_Integer_Index] Off
                  • Set PW_Point_OffsetLoc = (PW_Point_DummyLoc offset by PW_Real_TrueSpeed towards (Facing of PW_Unit_Dummy[PW_Integer_Index]) degrees)
                  • Unit - Move PW_Unit_Dummy[PW_Integer_Index] instantly to PW_Point_OffsetLoc, facing (Facing of PW_Unit_Dummy[PW_Integer_Index]) degrees
                  • Unit - Move PW_Unit_Target[PW_Integer_Index] instantly to PW_Point_OffsetLoc
                  • Set PW_Real_DragDistance[PW_Integer_Index] = (PW_Real_DragDistance[PW_Integer_Index] - PW_Real_TrueSpeed)
                  • Custom script: call RemoveLocation(udg_PW_Point_OffsetLoc)
                • Else - Actions
                  • Set PW_Point_CasterLoc = (Position of PW_Unit_Caster[PW_Integer_Index])
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Distance between PW_Point_DummyLoc and PW_Point_CasterLoc) Greater than PW_Real_ReturnDst[PW_Integer_Index]
                    • Then - Actions
                      • Set PW_Point_OffsetLoc = (PW_Point_DummyLoc offset by PW_Real_TrueSpeed towards (Angle from PW_Point_DummyLoc to PW_Point_CasterLoc) degrees)
                      • Unit - Move PW_Unit_Dummy[PW_Integer_Index] instantly to PW_Point_OffsetLoc, facing PW_Point_CasterLoc
                      • Unit - Move PW_Unit_Target[PW_Integer_Index] instantly to PW_Point_OffsetLoc
                      • Custom script: call RemoveLocation(udg_PW_Point_OffsetLoc)
                    • Else - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • PW_Boolean_DamageDealt[PW_Integer_Index] Equal to False
                        • Then - Actions
                          • Unit - Turn collision for PW_Unit_Target[PW_Integer_Index] On
                          • Unit - Kill PW_Unit_Dummy[PW_Integer_Index]
                          • Custom script: call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", GetUnitX(udg_PW_Unit_Dummy[udg_PW_Integer_Index]), GetUnitY(udg_PW_Unit_Dummy[udg_PW_Integer_Index])))
                          • Set PW_UG_Enemies = (Units within PW_Real_AoE[PW_Integer_Index] of PW_Point_DummyLoc matching ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of (Owner of PW_Unit_Caster[PW_Integer_Index])) Equal to True)))
                          • Unit Group - Pick every unit in PW_UG_Enemies and do (Actions)
                            • Loop - Actions
                              • Unit - Cause PW_Unit_Caster[PW_Integer_Index] to damage (Picked unit), dealing PW_Real_Dmg[PW_Integer_Index] damage of attack type Magic and damage type Magic
                          • Set PW_Boolean_DamageDealt[PW_Integer_Index] = True
                          • Custom script: call DestroyGroup(udg_PW_UG_Enemies)
                          • Set PW_Integer_Max = (PW_Integer_Max - 1)
                        • Else - Actions
                  • Custom script: call RemoveLocation(udg_PW_Point_CasterLoc)
          • Set PW_UG_Knockback = (Units within PW_Real_AoE[PW_Integer_Index] of PW_Point_DummyLoc matching (((((Matching unit) is alive) Equal to True) and ((Matching unit) Not equal to PW_Unit_Target[PW_Integer_Index])) and (((Matching unit) belongs to an enemy of (Owner of PW_Unit_Caster[P
          • Unit Group - Pick every unit in PW_UG_Knockback and do (Actions)
            • Loop - Actions
              • Set PW_Point_EnumLoc = (Position of (Picked unit))
              • Set PW_Point_OffsetLoc = (PW_Point_EnumLoc offset by PW_Real_TrueSpeed towards (Angle from PW_Point_DummyLoc to PW_Point_EnumLoc) degrees)
              • Unit - Move (Picked unit) instantly to PW_Point_OffsetLoc
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ((Picked unit) has buff Phoenix Wave ) Equal to False
                • Then - Actions
                  • Unit - Create 1 Phoenix Wave Dummy (DoT Effect) for (Owner of PW_Unit_Caster[PW_Integer_Index]) at PW_Point_DummyLoc facing Default building facing degrees
                  • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
                  • Unit - Order (Last created unit) to Neutral Alchemist - Acid Bomb (Picked unit)
                  • Custom script: call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl", GetEnumUnit(), "chest"))
                • Else - Actions
              • Custom script: call RemoveLocation(udg_PW_Point_EnumLoc)
              • Custom script: call RemoveLocation(udg_PW_Point_OffsetLoc)
          • Custom script: call RemoveLocation(udg_PW_Point_DummyLoc)
          • Custom script: call RemoveLocation(udg_PW_Point_TargetLoc)
          • Custom script: call DestroyGroup(udg_PW_UG_Knockback)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • PW_Integer_Max Equal to 0
        • Then - Actions
          • Set PW_Integer_Count = 0
          • Trigger - Turn off (This trigger)
        • Else - Actions


UPDATE:
- attempted trigger leak fixes

Please give credits if used. Any comment is appreciated!

Keywords:
phoenix, wave, fire, drag, bird, ravage, devastate, spell, gui, ultimate
Contents

Phoenix Wave v1 (Map)

Reviews
12th Dec 2015 IcemanBo: Too long as NeedsFix. Rejected. BPower: http://www.hiveworkshop.com/forums/spells-569/phoenix-wave-v1-193478/?prev=status%3Dp%26of%3Ddateline%26o%3DASC%26imporder%3D1#post2552865 Bribe (Position of (Target unit of...

Moderator

M

Moderator

12th Dec 2015
IcemanBo: Too long as NeedsFix. Rejected.

BPower:
http://www.hiveworkshop.com/forums/spells-569/phoenix-wave-v1-193478/?prev=status%3Dp%26of%3Ddateline%26o%3DASC%26imporder%3D1#post2552865

Bribe

(Position of (Target unit of ability being cast)) -> (Target point of ability being cast) # One less function call

Array[1] -> Variable1 # If it doesn't need to be an array, don't make it an array.

(Owner of (Triggering unit)) -> (Triggering player) # One less function call

Lots of memory leaks in Phoenix Wave Loop.
 
Level 6
Joined
Aug 20, 2009
Messages
95
Bribe said:
Bribe

(Position of (Target unit of ability being cast)) -> (Target point of ability being cast) # One less function call

Array[1] -> Variable1 # If it doesn't need to be an array, don't make it an array.

(Owner of (Triggering unit)) -> (Triggering player) # One less function call

Lots of memory leaks in Phoenix Wave Loop.

Please specify those, as I didn't see any in my brief checkup, and furthermore, you have no right to reject it when you A. Don't post where the memory leaks are, and B. The only thing you complained about were a few efficiency things. It functions, and functions well.

Tested: Heres my review.
Spell Idea - 4
Triggering - 5
Special Effects - 5
Therefore, you get a 5/5.

Comments -
I think the knockback might be a little bit instant, but that doesn;t matter.
The only thing I noticed as a bug, was that when a unit dies from the burn damage, the caster doesn't get the gold.
 
The configurables must support multiple levels in order to meet hive requirements


  • Unit - Move PW_Unit_Dummy[PW_Integer_Index] instantly to PW_Point_OffsetLoc, facing (Angle from PW_Point_DummyLoc to PW_Point_TargetLoc) degrees
The move function is an inefficient method and generates lag when many things are using it, using SetUnitX/SetUnitY will prevent lag being generated when other spells which also have "Move" are running.

  • Custom script: call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", GetUnitX(udg_PW_Unit_Dummy[udg_PW_Integer_Index]), GetUnitY(udg_PW_Unit_Dummy[udg_PW_Integer_Index])))
Special effects should also be configurables instead of hard-coded. Also if you were using co-ordinates for movement throughout the whole spell (as suggested) the end of this line would just be two variable references instead of needing to run extra functions to fetch them

  • Set PW_Integer_Max = (PW_Integer_Max - 1)
While this does make the spell able to stop running, there's no garuntee the last entry will be the first to end as such, the index recyling is buggy.

  • Unit - Kill PW_Unit_Dummy[PW_Integer_Index]
You kill the dummy, but never remove it (which it should be) I suggest adding an artificial wait between it's death and recycling if you want death animations to still play

  • Unit - Create 1 Phoenix Wave Dummy (Phoenix) for (Triggering player) at PW_Point_CasterLoc facing (Angle from PW_Point_CasterLoc to PW_Point_TargetLoc) degrees
The dummy unit type ought to be configurable as well

  • Unit - Order (Last created unit) to Neutral Alchemist - Acid Bomb (Picked unit)
Object editor based damage isn't what you'd call good, but I suppose it's alright for minor "extra" damage

That should just about do it, the spell looks fine otherwise
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
You should add a configuration trigger, where effects, damage, ability, aoe, damagetype, attacktype, ... can be setup.
"Picked Unit" could be stored into a variable in order to avoid needless function calls.

Please also take care of what the Tank-Commander posted. (Thank you)

Need Fix at the moment.
 
Top