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

I need help fixing a fire spell.

Status
Not open for further replies.
Level 9
Joined
Apr 19, 2011
Messages
447
Hi everyone.

I was trying to trigger a spell for my custom race (for me, probably one of the hardest spells of the race), and although the triggers look fine to me, the result is a mess. First of all, you need to know how the spell should work.
The race has a spellcaster, the Gnoll Summoner, that can summon small units called "Fire Spirits". They are weak by themselves, but they work as "food" for the ultimate spell of one of the other two spellcasters, the "Fire Elemental". The spell of the elemental (the one I need help with), is this one:

Volcanic Eruption: It's a passive ability. If you take a Fire Spirit and make it approach a Fire Elemental, the elemental will "absorb" the spirit (spirit gets invulnerable and starts rotating in circles around the elemental, in a ring shape). When the elemental gathers 5 spirits, the ring rotates faster and faster during 5 seconds, and then it disappears. The elemental targets the nearest enemy unit in a certain range, and creates a big explosion over that unit, dealing massive damage to all enemy units around. It there's no enemies around when the spell is cast, it does nothing. Then, the elemental can start gathering spirits again.

At first, I thought this spell was too much for me :xxd:, but I got some ideas about how to face it, and gave it a try. However, the result is a disaster. Here are my triggers:

The spell requires the "Fire Affinity" upgrade to be functional, so in this trigger I check whenever a player completes this research.
  • Volcanic Eruption Upgrade
    • Events
      • Unit - A unit Finishes a research
    • Conditions
      • (Researched tech-type) Equal to Fire Affinity
    • Actions
      • -------- I set as true in a boolean vector the position corresponding to the player that finished the research. --------
      • Set Upgrade_Volcanic_Eruption[(Player number of (Owner of (Triggering unit)))] = True
      • -------- I add all the Fire Elementals that the player has already trained to a unit group and set up the corresponding fields in a hashtable --------
      • Unit Group - Pick every unit in (Units owned by (Owner of (Triggering unit)) of type Fire Elemental) and do (Actions)
        • Loop - Actions
          • Set Key = (Key (Picked unit))
          • -------- 0: Number of Fire Spirits the elemental has gathered. Starts in 0. --------
          • Hashtable - Save 0 as 0 of Key in Volcanic_Eruption
          • -------- 1: The position that the next Fire Spirit will take in the ring around the elemental. Starts in 1. --------
          • -------- All the positions from 2 to 6 will be used to store the spirits. --------
          • -------- The position 7 is unused. --------
          • Hashtable - Save 1 as 1 of Key in Volcanic_Eruption
          • -------- 8: A boolean that I use to check if the elemental has already gathered 5 Fire Spirits and is casting the spell. Starts as false. --------
          • Hashtable - Save False as 8 of Key in Volcanic_Eruption
          • -------- 9: I use this real for timing. The gathering of spirits is instant, but the casting of the spell is timed. Starts in 0. --------
          • Hashtable - Save 0.00 as 9 of Key in Volcanic_Eruption
          • -------- 10: I use this real to set up how many degrees does the ring of spirits rotate around the elemental each 0.03 seconds. During the casting of the spell, the rings starts rotating faster and faster, and there's where I work with this value. --------
          • Hashtable - Save 10.00 as 10 of Key in Volcanic_Eruption
          • -------- This is the unit group where all the Fire Elementals with the ability go, and the group I use in the loop trigger. --------
          • Unit Group - Add (Picked unit) to Casters_Volcanic_Eruption
In this trigger, I repeat the proccess from before, but whenever a player trains a Fire Elemental. I use the boolean vector from the previous trigger to check if the player has researched "Fire Affinity".
  • Volcanic Eruption Training
    • Events
      • Unit - A unit Finishes training a unit
    • Conditions
      • (Unit-type of (Trained unit)) Equal to Fire Elemental
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Upgrade_Volcanic_Eruption[(Player number of (Owner of (Triggering unit)))] Equal to True
        • Then - Actions
          • Set Key = (Key (Trained unit))
          • Hashtable - Save 0 as 0 of Key in Volcanic_Eruption
          • Hashtable - Save 1 as 1 of Key in Volcanic_Eruption
          • Hashtable - Save False as 8 of Key in Volcanic_Eruption
          • Hashtable - Save 0.00 as 9 of Key in Volcanic_Eruption
          • Hashtable - Save 10.00 as 10 of Key in Volcanic_Eruption
          • Unit Group - Add (Trained unit) to Casters_Volcanic_Eruption
        • Other - Actions
This trigger is the main body of the spell. As you can imagine, the spell gets messed up here.
  • Volcanic Eruption Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in Casters_Volcanic_Eruption and do (Actions)
        • Loop - Actions
          • Set Key = (Key (Picked unit))
          • -------- First of all, I check if the elemental has already gathered the neccesary spirits for the spell. --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Load 8 of Key from Volcanic_Eruption) Equal to True
            • Then - Actions
              • -------- If all the required spirits have been gathered, I launch the spell. --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Load 9 of Key from Volcanic_Eruption) Lesser than 5.00
                • Then - Actions
                  • -------- When the spell starts casting, the speed of the ring increases during 5 seconds. --------
                  • Hashtable - Save ((Load 9 of Key from Volcanic_Eruption) + 0.03) as 9 of Key in Volcanic_Eruption
                  • Tabla hash - Save ((Load 10 of Key from Volcanic_Eruption) + 0.24) as 10 of Key in Volcanic_Eruption
                  • Set TempLoc = (Position of (Picked unit))
                  • -------- The fields "2,3,4,5,6" are where I store the spirits. --------
                  • For each (Integer INTEGER) from 2 to 6, do (Actions)
                    • Loop - Actions
                      • Set TempUnit = (Load INTEGER of Key in Volcanic_Eruption)
                      • Set TempLoc02 = (Position of TempUnit)
                      • Set TempLoc03 = (TempLoc offset by 150.00 towards ((Angle from TempLoc to TempLoc02) - (Load 10 of Key from Volcanic_Eruption)) degrees)
                      • Custom script: call SetUnitX(udg_TempUnit, GetLocationX(udg_TempLoc03))
                      • Custom script: call SetUnitY(udg_TempUnit, GetLocationY(udg_TempLoc03))
                      • Custom script: call RemoveLocation(udg_TempLoc02)
                      • Custom script: call RemoveLocation(udg_TempLoc03)
                  • Custom script: call RemoveLocation(udg_TempLoc)
                • Other - Actions
                  • -------- After 5 seconds, the effect of the spell starts. --------
                  • Set TempLoc = (Position of (Picked unit))
                  • -------- I destroy the spirits of the ring. --------
                  • For each (Integer INTEGER) from 2 to 6, do (Actions)
                    • Loop - Actions
                      • Unit - Kill (Load INTEGER of Key in Volcanic_Eruption)
                  • -------- I restart all the fields in the hashtable, so the elemental can cast the spell again if he gathers 5 spirits again. --------
                  • Hashtable - Save 0 as 0 of Key in Volcanic_Eruption
                  • Hashtable - Save 1 as 1 of Key in Volcanic_Eruption
                  • Hashtable - Save False as 8 of Key in Volcanic_Eruption
                  • Hashtable - Save 0.00 as 9 of Key in Volcanic_Eruption
                  • Hashtable - Save 10.00 as 10 of Key in Volcanic_Eruption
                  • Set TempUnit = (Picked unit)
                  • -------- From here on, I take the nearest enemy and do the damage. --------
                  • Unit Group - Pick every unit in (Units within 1000.00 of TempLoc matching (((Owner of (Matching unit)) is an enemy of (Owner of TempUnit)) Equal to True)) and do (Actions)
                    • Loop - Actions
                      • Unit Group - Add (Picked unit) to TempGroup
                  • Set TempUnit = (Random unit from TempGroup)
                  • Set TempLoc02 = (Position of TempUnit)
                  • Set TempReal = (Distance between TempLoc and TempLoc02)
                  • Custom script: call RemoveLocation(udg_TempLoc02)
                  • Unit Gorup - Pick every unit in TempGroup and do (Actions)
                    • Loop - Actions
                      • Set TempLoc02 = (Position of (Picked unit))
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (Distance between TempLoc and TempLoc02) Lesser than TempReal
                        • Then - Actions
                          • Set TempReal = (Distance between TempLoc and TempLoc02)
                          • Set TempUnit = (Picked unit)
                        • Other - Actions
                  • Custom script: call RemoveLocation(udg_TempLoc)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • TempUnit Equal to No unit
                    • Then - Actions
                    • Other - Actions
                      • Set TempLoc = (Position of TempUnit)
                      • Sound - Play BuildingDeathLargeHuman <gen> at 100.00% volume, located at TempLoc with Z offset 0.00
                      • Special Effect - Create a special effect at TempLoc using war3campImported\NewMassiveEX.mdx
                      • Special Effect - Destroy (Last created special effect)
                      • Set TempUnit = (Picked unit)
                      • Unit Gorup - Pick every unit in (Units within 500.00 of TempLoc matching (((Owner of (Matching unit)) is an enemy of (Owner of (Picked unit))) Equal to True)) and do (Actions)
                        • Loop - Actions
                          • Unit - Cause TempUnit to damage (Picked unit), dealing 250.00 damage of attack type Spells and damage type Normal
                      • Custom script: call RemoveLocation(udg_TempLoc)
            • Other - Actions
              • -------- If there's still spirits left to gather, I run the gathering part of the trigger. --------
              • -------- First, I check if the elemental has 5 spirits. --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Load 0 of Key from Volcanic_Eruption) Equal to 5
                • Then - Actions
                  • -------- If he has 5 spirits, he's ready to cast the spell, so I set this boolean to true. This way, the next time the trigger fires, it will go through the casting part, and not through the gathering part. --------
                  • Hashtable - Save True as 8 of Key in Volcanic_Eruption
                • Other - Actions
                  • -------- If he does not have 5 spirits, I run the gathering. --------
                  • -------- First of all, I rotate the current spirits in the ring. --------
                  • Set TempLoc = (Position of (Picked unit))
                  • -------- The fields "2,3,4,5,6" are where I store the spirits. --------
                  • For each (Integer INTEGER) from 2 to 6, do (Actions)
                    • Loop - Actions
                      • Set TempUnit = (Load INTEGER of Key in Volcanic_Eruption)
                      • Set TempLoc02 = (Position of TempUnit)
                      • Set TempLoc03 = (TempLoc offset by 150.00 towards ((Angle from TempLoc to TempLoc02) - (Load 10 of Key from Volcanic_Eruption)) degrees)
                      • Custom script: call SetUnitX(udg_TempUnit, GetLocationX(udg_TempLoc03))
                      • Custom script: call SetUnitY(udg_TempUnit, GetLocationY(udg_TempLoc03))
                      • Custom script: call RemoveLocation(udg_TempLoc02)
                      • Custom script: call RemoveLocation(udg_TempLoc03)
                  • -------- I pick all the friendly Fire Spirits in the gathering range of the elemental (500), and I add them to a temporal unit group. --------
                  • Unit Group - Pick every unit in (Units within 500.00 of TempLoc matching (((Owner of (Matching unit)) Equal to (Owner of (Picked unit))) and ((Unit-type of (Matching unit)) Equal to Fire Spirit))) and do (Actions)
                    • Loop - Actions
                      • Unit Group - Add (Picked unit) to TempGroup
                  • -------- I select a random spirit from the available ones. --------
                  • Set TempUnit = (Random unit from TempGroup)
                  • -------- I check if the elemental actually has spirits around. --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • TempUnit Equal to No unit
                    • Then - Actions
                      • -------- I the search from before didn't get any spirits, I do nothing. --------
                    • Other - Actions
                      • -------- I play a sound, just to make it nice, and I kill the original spirit. --------
                      • Sound - Play LavaSpawnMissileBirth1 <gen> at 100.00% volume, attached to TempUnit
                      • -------- NOTE: I kill the original and then create a new one because the originals have expiration timers. I don't want the gathered spirits to disappear. --------
                      • Unit - Kill TempUnit
                      • -------- I check if this spirit is the first one to get added. --------
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (Load 1 of Key from Volcanic_Eruption) Equal to 1
                        • Then - Actions
                          • -------- If the spirit is the first one, I create it on the ring at 90 degrees (default). --------
                          • Set TempLoc02 = (TempLoc offset by 150.00 towards 90.00 degrees)
                          • Unit - Create 1 Fire Spirit for (Owner of (Picked unit)) at TempLoc02 facing Default building facing degrees
                          • Set TempUnit = (Last created unit)
                          • Custom script: call UnitAddAbility(udg_TempUnit, 'Aloc')
                          • Animation - Play (Last created unit)'s birth animation
                          • Animation - Queue (Last created unit)'s stand animation
                          • Hashtable - Save Handle Of(Last created unit) as ((Load 1 of Key from Volcanic_Eruption) + 1) of Key in Volcanic_Eruption
                          • Custom script: call RemoveLocation(udg_TempLoc02)
                        • Other - Actions
                          • -------- If there's already spirits in the ring, I get the position of the last one that was added, and create the new one so they are all at the same distance. --------
                          • Set TempLoc02 = (Position of (Load (1 + (Load 0 of Key from Volcanic_Eruption)) of Key in Volcanic_Eruption))
                          • Set TempLoc03 = (TempLoc offset by 150.00 towards ((Angle from TempLoc to TempLoc02) - 72.00) degrees)
                          • Unit - Create 1 Fire Spirit for (Owner of (Picked unit)) at TempLoc03 facing Default building facing degrees
                          • Set TempUnit = (Last created unit)
                          • Custom script: call UnitAddAbility(udg_TempUnit, 'Aloc')
                          • Animation - Play (Last created unit)'s birth animation
                          • Animation - Queue (Last created unit)'s stand animation
                          • Hashtable - Save Handle Of(Last created unit) as ((Load 1 of Key from Volcanic_Eruption) + 1) of Key in Volcanic_Eruption
                          • Custom script: call RemoveLocation(udg_TempLoc02)
                          • Custom script: call RemoveLocation(udg_TempLoc03)
                      • -------- I increse in 1 the amount of spirits. When this value gets to 5, the gathering is over, and the trigger should go through the casting part. --------
                      • Hashtable - Save ((Load 0 of Key from Volcanic_Eruption) + 1) as 0 of Key in Volcanic_Eruption
                      • -------- I update the position in which the next gathered spirit will be stored. --------
                      • Hashtable - Save ((Load 1 of Key from Volcanic_Eruption) + 1) as 1 of Key in Volcanic_Eruption
                  • Custom script: call RemoveLocation(udg_TempLoc)
OK, the mess happens when the first Fire Spirit gets near the elemental. It disappears, and then, instead of creating a single spirit at 90 degrees (that should start rotating), it starts mass-creating spirits at an angle of about 30-40 degrees (and they do not move at all).
My logic keeps telling me that the triggers are alright. But obviously, they aren't. Can someone help me find the issue? Also, it would be helpful if you could help me make this spell more efficient, because right now I'm pretty sure it's not as efficient as it can be.

Kind Regards
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
U leak all ur groups

Anything u use twice or more store into a variable and use that instead.

There is most likely a problem with ur hashtables. I can't see it exactly Im on my phone
U should learn how to use indexed arrays. It is much simpler to make. There is a chapter called how to index in my GUI tutorial in my sig

Look for when u create the new unit and there should be ur problem. If u could show were that is exactly I can help more i hope
 
Level 9
Joined
Apr 19, 2011
Messages
447
U leak all ur groups

Anything u use twice or more store into a variable and use that instead.

There is most likely a problem with ur hashtables. I can't see it exactly Im on my phone
U should learn how to use indexed arrays. It is much simpler to make. There is a chapter called how to index in my GUI tutorial in my sig

Look for when u create the new unit and there should be ur problem. If u could show were that is exactly I can help more i hope

Whoa, you're right, I forgot the group leaks, thanks for pointing that, I'll fix it.
And well, indexing is one of my current goals. I'll take a look at your tutorial, and see if I can at least understand how it works, and how to use it in my own spells, and so.

About the issue with my spell, I also think the problem is in the part where I create the new units (I just don't get what's wrong). If it helps, this is that part of the trigger:


NOTE: The If\Then\Else surrounded by the "XXXXX" comments is the one that creates the units.
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (Load 0 of Key from Volcanic_Eruption) Equal to 5
    • Then - Actions
      • -------- If he has 5 spirits, he's ready to cast the spell, so I set this boolean to true. This way, the next time the trigger fires, it will go through the casting part, and not through the gathering part. --------
      • Hashtable - Save True as 8 of Key in Volcanic_Eruption
    • Other - Actions
      • -------- If he does not have 5 spirits, I run the gathering. --------
      • -------- First of all, I rotate the current spirits in the ring. --------
      • Set TempLoc = (Position of (Picked unit))
      • -------- The fields "2,3,4,5,6" are where I store the spirits. --------
      • For each (Integer INTEGER) from 2 to 6, do (Actions)
        • Loop - Actions
          • Set TempUnit = (Load INTEGER of Key in Volcanic_Eruption)
          • Set TempLoc02 = (Position of TempUnit)
          • Set TempLoc03 = (TempLoc offset by 150.00 towards ((Angle from TempLoc to TempLoc02) - (Load 10 of Key from Volcanic_Eruption)) degrees)
          • Custom script: call SetUnitX(udg_TempUnit, GetLocationX(udg_TempLoc03))
          • Custom script: call SetUnitY(udg_TempUnit, GetLocationY(udg_TempLoc03))
          • Custom script: call RemoveLocation(udg_TempLoc02)
          • Custom script: call RemoveLocation(udg_TempLoc03)
      • -------- I pick all the friendly Fire Spirits in the gathering range of the elemental (500), and I add them to a temporal unit group. --------
      • Unit Group - Pick every unit in (Units within 500.00 of TempLoc matching (((Owner of (Matching unit)) Equal to (Owner of (Picked unit))) and ((Unit-type of (Matching unit)) Equal to Fire Spirit))) and do (Actions)
        • Loop - Actions
          • Unit Group - Add (Picked unit) to TempGroup
      • -------- I select a random spirit from the available ones. --------
      • Set TempUnit = (Random unit from TempGroup)
      • -------- I check if the elemental actually has spirits around. --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • TempUnit Equal to No unit
        • Then - Actions
          • -------- I the search from before didn't get any spirits, I do nothing. --------
        • Other - Actions
          • -------- I play a sound, just to make it nice, and I kill the original spirit. --------
          • Sound - Play LavaSpawnMissileBirth1 <gen> at 100.00% volume, attached to TempUnit
          • -------- NOTE: I kill the original and then create a new one because the originals have expiration timers. I don't want the gathered spirits to disappear. --------
          • Unit - Kill TempUnit
          • -------- I check if this spirit is the first one to get added. --------
          • -------- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Load 1 of Key from Volcanic_Eruption) Equal to 1
            • Then - Actions
              • -------- If the spirit is the first one, I create it on the ring at 90 degrees (default). --------
              • Set TempLoc02 = (TempLoc offset by 150.00 towards 90.00 degrees)
              • Unit - Create 1 Fire Spirit for (Owner of (Picked unit)) at TempLoc02 facing Default building facing degrees
              • Set TempUnit = (Last created unit)
              • Custom script: call UnitAddAbility(udg_TempUnit, 'Aloc')
              • Animation - Play (Last created unit)'s birth animation
              • Animation - Queue (Last created unit)'s stand animation
              • Hashtable - Save Handle Of(Last created unit) as ((Load 1 of Key from Volcanic_Eruption) + 1) of Key in Volcanic_Eruption
              • Custom script: call RemoveLocation(udg_TempLoc02)
            • Other - Actions
              • -------- If there's already spirits in the ring, I get the position of the last one that was added, and create the new one so they are all at the same distance. --------
              • Set TempLoc02 = (Position of (Load (1 + (Load 0 of Key from Volcanic_Eruption)) of Key in Volcanic_Eruption))
              • Set TempLoc03 = (TempLoc offset by 150.00 towards ((Angle from TempLoc to TempLoc02) - 72.00) degrees)
              • Unit - Create 1 Fire Spirit for (Owner of (Picked unit)) at TempLoc03 facing Default building facing degrees
              • Set TempUnit = (Last created unit)
              • Custom script: call UnitAddAbility(udg_TempUnit, 'Aloc')
              • Animation - Play (Last created unit)'s birth animation
              • Animation - Queue (Last created unit)'s stand animation
              • Hashtable - Save Handle Of(Last created unit) as ((Load 1 of Key from Volcanic_Eruption) + 1) of Key in Volcanic_Eruption
              • Custom script: call RemoveLocation(udg_TempLoc02)
              • Custom script: call RemoveLocation(udg_TempLoc03)
          • -------- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX --------
          • -------- I increse in 1 the amount of spirits. When this value gets to 5, the gathering is over, and the trigger should go through the casting part. --------
          • Hashtable - Save ((Load 0 of Key from Volcanic_Eruption) + 1) as 0 of Key in Volcanic_Eruption
          • -------- I update the position in which the next gathered spirit will be stored. --------
          • Hashtable - Save ((Load 1 of Key from Volcanic_Eruption) + 1) as 1 of Key in Volcanic_Eruption
      • Custom script: call RemoveLocation(udg_TempLoc)
Thanks for helping.

Kind Regards
 
Status
Not open for further replies.
Top