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

Spell crashes game

Status
Not open for further replies.
Level 3
Joined
Jan 19, 2009
Messages
27
Hey everyone, I'm trying to make lightning shield - like ability, but I need it do deal damage only to enemies, so I had to use triggers... However, each time I cast it ingame, the game crashes. I realised that the problem is in second trigger. Here are triggers
Lightning Shield Cast
  • Events
    • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Lightning Shield
    • Actions
      • Set LSUnit[(Player number of (Owner of (Triggering unit)))] = (Target unit of ability being cast)
      • Unit Group - Add LSUnit[(Player number of (Owner of (Triggering unit)))] to LSGroup
      • Hashtable - Create a hashtable
      • Set LSHash = (Last created hashtable)
      • Hashtable - Save (Player number of (Owner of (Triggering unit))) as 0 of (Key (Target unit of ability being cast)) in LSHash
      • Wait until ((LSUnit[(Player number of (Owner of (Triggering unit)))] has buff Lightning Shield) Equal to True), checking every 0.10 seconds
      • Unit Group - Remove LSUnit[(Player number of (Owner of (Triggering unit)))] from LSGroup
Ligtning Shield Effect
  • Events
    • Time - Every 1.00 seconds of game time
    • Conditions
      • (Number of units in LSGroup) Greater than 0
    • Actions
      • Unit Group - Pick every unit in LSGroup and do (Actions)
        • Loop - Actions
          • Set Integer = (Key (Load 0 of (Key (Picked unit)) in LSHash))
          • Set Point = (Position of (Picked unit))
          • Set TempUnitGroup = (Units within 160.00 of Point matching ((((Matching unit) is A structure) Equal to False) and ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of (Player(Integer))) Equal to True))))
          • Custom script: call RemoveLocation(udg_Point)
          • Unit Group - Pick every unit in TempUnitGroup and do (Actions)
            • Loop - Actions
              • Unit - Cause Hero[Integer] to damage (Picked unit), dealing (20.00 + (AbilityPower[Integer] x 0.33)) damage of attack type Spells and damage type Lightning
          • Set Integer = 0
I also tried using Custom value instead of Hashtables but the same thing happens.
 
Level 6
Joined
Oct 4, 2011
Messages
226
Hashtables are only created once at map initialization, you shouldn't use "wait" or remove the unit group in the first trigger, this should be done during the second trigger. To keep track of how long you want the effect "shield" to last you should save a "Real" in a hashtable, Then in the second trigger set a variable to the loaded value from the hashtable, if the variable is greater then 0 then do:(save RealVariable - .03 as 1 of IdInteger in Hashtable), Else do:(UnitGroup remove TempUnit from LSGroup, Hashtable clear child of IdInteger). You have to change the second triggers time from 1.00 to .03 so it can count more independtly depending on if more then 1 unit will have this spell. In the second trigger all the actions should be under an "If then else then" under the section "then". Under the section "Else" place "turn off this trigger" The condition should be an integer condition, "Number of units in LSGroup Greater then 0". These are some steps to help your spell sorry it isn't summarized.
 
Level 3
Joined
Jan 19, 2009
Messages
27
Here are some changes I've made:
Lightning Shield Cast
  • Events
    • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Lightning Shield
    • Actions
      • Set LSUnit[(Player number of (Owner of (Triggering unit)))] = (Target unit of ability being cast)
      • Unit Group - Add LSUnit[(Player number of (Owner of (Triggering unit)))] to LSGroup
      • Hashtable - Save (Player number of (Owner of (Triggering unit))) as 0 of (Key (Target unit of ability being cast)) in LSHash
      • Hashtable - Save 10.00 as 1 of (Key (Target unit of ability being cast)) in LSHash
      • Unit - Order Dummy1 0023 <gen> to Undead Banshee - Curse LSUnit[(Player number of (Owner of (Triggering unit)))]
Ligtning Shield Effect
  • Events
    • Time - Every 1.00 seconds of game time
    • Conditions
      • (Number of units in LSGroup) Greater than 0
    • Actions
      • Game - Display to (All players) the text: a
      • Unit Group - Pick every unit in LSGroup and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Load 1 of (Key (Picked unit)) from LSHash) Not equal to 0.00
              • ((Picked unit) is alive) Equal to True
            • Then - Actions
              • Set Integer = (Key (Load 0 of (Key (Picked unit)) in LSHash))
              • Set Point = (Position of (Picked unit))
              • Set TempUnitGroup = (Units within 160.00 of Point matching ((((Matching unit) is A structure) Equal to False) and ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of (Player(Integer))) Equal to True))))
              • Custom script: call RemoveLocation(udg_Point)
              • Hashtable - Save ((Load 1 of (Key (Picked unit)) from LSHash) - 1.00) as 1 of (Key (Picked unit)) in LSHash
              • Unit Group - Pick every unit in TempUnitGroup and do (Actions)
                • Loop - Actions
                  • Special Effect - Create a special effect attached to the chest of (Picked unit) using Abilities\Spells\Orc\LightningShield\LightningShieldBuff.mdl
                  • Unit - Cause Hero[Integer] to damage (Picked unit), dealing (20.00 + (AbilityPower[Integer] x 0.33)) damage of attack type Spells and damage type Lightning
                  • Special Effect - Destroy (Last created special effect)
              • Set Integer = 0
            • Else - Actions
              • Unit Group - Remove (Picked unit) from LSGroup
I couldn't change event in second trigger to 0.03, because I need the spell to deal damage each second. But it's still crashing... Maybe I need to make a variable for unit and not refer it as "Picked unit"?
 
Level 3
Joined
Jan 19, 2009
Messages
27
OK, I have posted the sample map. I have slightly modified the trigger to check whether unit has buff instead of checking real variable... The result is still game crash... I can only get rid of it after I delete all actions involving Hashtables...
 

Attachments

  • SampleLigtningShield.w3x
    57.1 KB · Views: 51
Level 6
Joined
Oct 4, 2011
Messages
226
There are many things that are done wrong at the moment. The variable "LSUnit" should not be an array type variable. The way you are saving your hashtable information doesn't work. Maker taught me a way to save hashtable information and it helps alot. I need you to create an Integer variable "no array" name the variable "LSId_Integer". This will be what you save everything to. every info you want to store will be a number, of LSId_Integer of LSHash. But first you have to make LSId_Integer = Target unit. This will done using a line of custom script.
  • Custom script: set udg_LSId_Integer = GetHandleId(udg_LSUnit)
The only thing you need to know to change is "LSUnit" you put whatever the name of the unit variable is there. So first save LSUnit the target unit of ability being cast and then make this custom script afterwards. Now when you save your hashtable information it will be saved to actual information which will be the unit. And when the conditions are right you will be able to clear the information easily by clearing the child hashtable clear the LSId_Integer and locations should be removed probably at the same time, using custom script "Call RemoveLocation(udg_NAME)". before you can check your real variable condition you have to set the value first to make the comparison. also do still use Pick every unit in LSGroup but then early on set picked unit to a unit variable, most variables can be used for more then 1 spell if done right. so we will call this unit TempUnit, set TempUnit = picked unit and then this can be used for all of the units. In the loop trigger to transfer the information over you still need to actively set the LSId_Integer,
  • Custom script: set udg_LSId_Integer = GetHandleId(udg_TempUnit)
This should be done pretty early in the loop also and then your hashtable values will be actively kept up with. KEEP TRYING I TOO AM ONLY GETTING BETTER I JUST LEARNED ABOUT HASHTABLES A MONTH AGO :)
 
Level 3
Joined
Jan 19, 2009
Messages
27
Sry for the late reply, I'm quite busy these days...

There are many things that are done wrong at the moment. The variable "LSUnit" should not be an array type variable. The way you are saving your hashtable information doesn't work. Maker taught me a way to save hashtable information and it helps alot. I need you to create an Integer variable "no array" name the variable "LSId_Integer". This will be what you save everything to. every info you want to store will be a number, of LSId_Integer of LSHash. But first you have to make LSId_Integer = Target unit. This will done using a line of custom script.
  • Custom script: set udg_LSId_Integer = GetHandleId(udg_LSUnit)
The only thing you need to know to change is "LSUnit" you put whatever the name of the unit variable is there. So first save LSUnit the target unit of ability being cast and then make this custom script afterwards. Now when you save your hashtable information it will be saved to actual information which will be the unit. And when the conditions are right you will be able to clear the information easily by clearing the child hashtable clear the LSId_Integer and locations should be removed probably at the same time, using custom script "Call RemoveLocation(udg_NAME)". before you can check your real variable condition you have to set the value first to make the comparison. also do still use Pick every unit in LSGroup but then early on set picked unit to a unit variable, most variables can be used for more then 1 spell if done right. so we will call this unit TempUnit, set TempUnit = picked unit and then this can be used for all of the units. In the loop trigger to transfer the information over you still need to actively set the LSId_Integer,
  • Custom script: set udg_LSId_Integer = GetHandleId(udg_TempUnit)
This should be done pretty early in the loop also and then your hashtable values will be actively kept up with. KEEP TRYING I TOO AM ONLY GETTING BETTER I JUST LEARNED ABOUT HASHTABLES A MONTH AGO :)

Ah... I'm totaly new to the hashtables so this is completely confusing for me x)... I would greatly appreciate if you could post me a trigger where you put all this...
 
Just so you know, one thing that often causes wc3 to crash, is setting some values to "0" in certain spells. I know for instance that some interval or duration values in "shockwave" and that spell that maiev has will cause infinite loops in the game and cause it to crash.
Just somethng you might want to consider.
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
- never use arrayed variables when using hash coz it's already indexed (arrayed) by using
child keys...
- do not put condition in your trigger looper...
- change the condition 'Not equal to 0.00' to greter than 0...
- do not remove your unit from group unless spell is done, then off the trigger...
- AbilityPower[Integer] ???, maybe this causes the crash?...
 
Level 3
Joined
Jan 19, 2009
Messages
27
Finally got it to work... It seems that this was the problem:
  • Set Integer = (Key (Load 0 of (Key (Picked unit)) in LSHash))
After changing it to this:
  • Set Integer = (Load 0 of (Key (Picked unit)) from LSHash)
it worked :) Thx everyone for reply, I will try to optimize it as much as possible.
 
Status
Not open for further replies.
Top