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

Need Help for Avenging Wrath

Status
Not open for further replies.
Level 2
Joined
Apr 16, 2012
Messages
8
Hi to all,

i tried to create spell (Avenging Wrath) of paladin hero class in world of Warcraft. but somehow my spell dosen't work very well . i did my best to make it MUI but after the Second hero using that spell the variables going wild and make things messy. i want to increase spell power of hero for 15 seconds.

Skill based of "Roar" spell.

here's my GUI Codes

Aw1
Aw2
Aw3


ps : i tried to send pictures but it didn't work so i just sent links .

Best.
 
Level 39
Joined
Feb 27, 2007
Messages
5,008
You can post triggers by right clicking them and selecting "copy as text" then pasting on this forum between [trigger][/trigger] tags.

Second line of first trigger AWG_Loop should be AWG_Index. Your if block in that trigger seems real funky to me since it increases spell power for only the 1st index and only if no other indices are in use at the time the spell is cast. There's no guarantee that the indices of Spell_Power[] and AWG_<variable>[] are in sync, either... they could be referring to entirely different units. I can't really help you here if you're using/setting Spell_Power in other places in your map.

In trigger 3 you need to introduce a For each integer AWG_Loop from 1 to AWG_Index do Actions like you have in trigger 2. Then it will detect if the triggering unit is currently affected by Avenging Wrath and if so increase the heal:

  • Actions
    • Set FH_Heal = 0.00 //or whatever your base heal without spellpower is (the way you've written it now is 0 base heal)
    • For each integer AWG_Loop from 1 to AWG_Index do (Actions)
      • Loop - Actions
        • If (all conditions are true) then do (Then actions) else do (else actions)
          • If - Conditions
            • (Triggering unit) equal to AWG_Caster[AWG_Loop]
          • Then - Actions
            • Set FH_Heal = FH_Heal + Spell_Power[AWG_Loop]
            • Custom script: exitwhen true //optional, this makes your trigger slightly more efficient
          • Else - Actions
    • Unit - Set life of (target unit of ability being cast) to ((current life of (target unit of ability being cast)) + FH_Heal)
Use integers instead of reals for AWG_Counter. Honestly if you're trying to make spell power a thing in your map, instead of trying to synch your arrays it'd be much easier to just use a hashtable and store each unit's current spell power under its handle id in the hashtable.
 
Level 2
Joined
Apr 16, 2012
Messages
8
You can post triggers by right clicking them and selecting "copy as text" then pasting on this forum between [trigger][/trigger] tags.

Second line of first trigger AWG_Loop should be AWG_Index. Your if block in that trigger seems real funky to me since it increases spell power for only the 1st index and only if no other indices are in use at the time the spell is cast. There's no guarantee that the indices of Spell_Power[] and AWG_<variable>[] are in sync, either... they could be referring to entirely different units. I can't really help you here if you're using/setting Spell_Power in other places in your map.

In trigger 3 you need to introduce a For each integer AWG_Loop from 1 to AWG_Index do Actions like you have in trigger 2. Then it will detect if the triggering unit is currently affected by Avenging Wrath and if so increase the heal:

  • Actions
    • Set FH_Heal = 0.00 //or whatever your base heal without spellpower is (the way you've written it now is 0 base heal)
    • For each integer AWG_Loop from 1 to AWG_Index do (Actions)
      • Loop - Actions
        • If (all conditions are true) then do (Then actions) else do (else actions)
          • If - Conditions
            • (Triggering unit) equal to AWG_Caster[AWG_Loop]
          • Then - Actions
            • Set FH_Heal = FH_Heal + Spell_Power[AWG_Loop]
            • Custom script: exitwhen true //optional, this makes your trigger slightly more efficient
          • Else - Actions
    • Unit - Set life of (target unit of ability being cast) to ((current life of (target unit of ability being cast)) + FH_Heal)
Use integers instead of reals for AWG_Counter. Honestly if you're trying to make spell power a thing in your map, instead of trying to synch your arrays it'd be much easier to just use a hashtable and store each unit's current spell power under its handle id in the hashtable.
you explained alot. But i much clearer now :)
ill try to use hashtable it might be better way, specialy for buff based spells.
You used custom scripts which i have no idea how to use them , if you link any tutorial it would be great.
Thank you very much ;)

Best wishes .
 
Level 39
Joined
Feb 27, 2007
Messages
5,008
Custom scripts are just the JASS code that your GUI triggers get converted into when you save/compile your map. If you want to see what that looks like, make a copy of one of your triggers, select it in the trigger editor, and then click Edit > Convert to Custom Text. This will convert that trigger to JASS. There are some things in JASS that have no GUI equivalent, so to use them you have to use custom script lines. A good example of this is removing leaks in your triggers.

In this case once you find an AWG_Caster[] that is the same as the triggering unit, you know you don't have to look through the rest of the AWG_Caster[]s to try to find another match, since you already found it. GUI doesn't have an action for "leave this loop without first finishing it" but that exitwhen true tells the game to exit the loop and continue on to the next line of code when it gets there. Not having it doesn't do anything bad to your map, it just keeps searching through the AWG_Caster[]s after it's already found a match.
 
Level 2
Joined
Apr 16, 2012
Messages
8
Custom scripts are just the JASS code that your GUI triggers get converted into when you save/compile your map. If you want to see what that looks like, make a copy of one of your triggers, select it in the trigger editor, and then click Edit > Convert to Custom Text. This will convert that trigger to JASS. There are some things in JASS that have no GUI equivalent, so to use them you have to use custom script lines. A good example of this is removing leaks in your triggers.

In this case once you find an AWG_Caster[] that is the same as the triggering unit, you know you don't have to look through the rest of the AWG_Caster[]s to try to find another match, since you already found it. GUI doesn't have an action for "leave this loop without first finishing it" but that exitwhen true tells the game to exit the loop and continue on to the next line of code when it gets there. Not having it doesn't do anything bad to your map, it just keeps searching through the AWG_Caster[]s after it's already found a match.

Thanks for your explanation. Just finished that spell with hashtables and handels. I tryed many times with many heroes(instances) and even killed a hero and i didnt saw any bug . I hope i could make it MUI .

I always wonder why gui dosent have "return" command like in c++ , c# , ...
So that's why ...

Btw , It's 4:30 here and i'm so sleepy. ill send map and triggers tomorow.

Thanks again :oops:
 
Level 2
Joined
Apr 16, 2012
Messages
8
"Skip remaining actions" in GUI is return in JASS :)

w0w thanks :D

here's my test Map For Spell and Triggers ...

  • Map init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set AVG_Table = (Last created hashtable)
  • AVG
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to AVG
    • Actions
      • Set AVG_Counter = (AVG_Counter + 1)
      • Hashtable - Save 200.00 as (Key spellpower) of (Key (Triggering unit)) in AVG_Table
      • Hashtable - Save 15.00 as (Key time) of (Key (Triggering unit)) in AVG_Table
      • Unit Group - Add (Triggering unit) to AVG_UnitGroup
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • AVG_Counter Equal to 1
        • Then - Actions
          • Trigger - Turn on AVG Loop <gen>
        • Else - Actions
  • AVG Loop
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in AVG_UnitGroup and do (Actions)
        • Loop - Actions
          • Set AVG_Timer = (Load (Key time) of (Key (Picked unit)) from AVG_Table)
          • Hashtable - Save (AVG_Timer - 1.00) as (Key time) of (Key (Picked unit)) in AVG_Table
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AVG_Timer Less than or equal to 0.00
            • Then - Actions
              • Set AVG_Counter = (AVG_Counter - 1)
              • Set AVG_Spl_Dmg = (Load (Key spellpower) of (Key (Picked unit)) from AVG_Table)
              • Hashtable - Save (AVG_Spl_Dmg - 200.00) as (Key spellpower) of (Key (Picked unit)) in AVG_Table
              • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in AVG_Table
              • Unit Group - Remove (Picked unit) from AVG_UnitGroup
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • AVG_Counter Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
            • Else - Actions
  • Heal
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Holy Light
    • Actions
      • Unit - Set life of (Target unit of ability being cast) to ((Life of (Target unit of ability being cast)) + (Load (Key spellpower) of (Key (Triggering unit)) from AVG_Table))
.... is it MUI ? o_O
 

Attachments

  • Avg.w3x
    20 KB · Views: 60
Level 39
Joined
Feb 27, 2007
Messages
5,008
Yes, you've written in properly to be MUI. There are only 2 further things you may wish to consider, but they are not very important:

1. Imagine one unit casts AVW, then a second unit waits 0.90 seconds and also casts AVW. After 0.1 seconds the trigger runs and reduces both instances of the spell to 14 remaining seconds; at that time both instances will end simultaneously even though the second was cast after. If your update period was every 0.1 seconds (not recommended, just an example) then in this example the second instance would properly end 0.9s after the first. So it's really only a problem with longer intervals; most players won't notice the difference between 14 and 15 seconds, but they would notice 20 vs. 30 seconds. I don't think you need to change the update period here, but you should be aware of this effect.

2. I suggested using a hashtable for spell power because I assumed other spells or items in your map might increase spell power for some units. If that is not the case, ignore me. If it is, though, instead of making a new hashtable for each spell like this I think you should just have one spell power hashtable that each spell refers to when determining damage and healing.
 
Level 2
Joined
Apr 16, 2012
Messages
8
Yes, you've written in properly to be MUI. There are only 2 further things you may wish to consider, but they are not very important:

1. Imagine one unit casts AVW, then a second unit waits 0.90 seconds and also casts AVW. After 0.1 seconds the trigger runs and reduces both instances of the spell to 14 remaining seconds; at that time both instances will end simultaneously even though the second was cast after. If your update period was every 0.1 seconds (not recommended, just an example) then in this example the second instance would properly end 0.9s after the first. So it's really only a problem with longer intervals; most players won't notice the difference between 14 and 15 seconds, but they would notice 20 vs. 30 seconds. I don't think you need to change the update period here, but you should be aware of this effect.

2. I suggested using a hashtable for spell power because I assumed other spells or items in your map might increase spell power for some units. If that is not the case, ignore me. If it is, though, instead of making a new hashtable for each spell like this I think you should just have one spell power hashtable that each spell refers to when determining damage and healing.

about number 1 problem, normally use 0.3 second period time (i used some Debug messages so i ratherd 1 second delay to watch them clearly)
i heard 0.3 is better than 0.1 for i don't know the reason ... .

about second problem i was aware of that and you hit the point.
yes i will have more spells and items on my map and going this way will make a huge mess.
trying to change it as you said and resend Triggers .

best :-*
 
Level 39
Joined
Feb 27, 2007
Messages
5,008
i heard 0.3 is better than 0.1 for i don't know the reason ... .
It's not 'better' for some all-encompassing reason. Just in general running many high-frequency periodic triggers can seriously slow down/lag your map, and if your periodic triggers leak objects/references the more frequently the triggers run the more quickly those leaks become a massive problem. Most GUI code is horribly inefficient because essentially everything is a wrapper function with arguments in reverse order, so the less frequently you can execute your code, the better. Well-written JASS can reliably be run at 0.03 or 0.01 without any real problems.

I usually pick something like 0.025 for things like knockbacks, moving effects, and other stuff that will only be active for a short time. If I can get away with being less precise I'll go for 0.25 or 0.5. It really depends on what you're doing and how much code overhead it has.
 
Level 2
Joined
Apr 16, 2012
Messages
8
It's not 'better' for some all-encompassing reason. Just in general running many high-frequency periodic triggers can seriously slow down/lag your map, and if your periodic triggers leak objects/references the more frequently the triggers run the more quickly those leaks become a massive problem. Most GUI code is horribly inefficient because essentially everything is a wrapper function with arguments in reverse order, so the less frequently you can execute your code, the better. Well-written JASS can reliably be run at 0.03 or 0.01 without any real problems.

I usually pick something like 0.025 for things like knockbacks, moving effects, and other stuff that will only be active for a short time. If I can get away with being less precise I'll go for 0.25 or 0.5. It really depends on what you're doing and how much code overhead it has.

Alright , so it depends on spell, and JASS is much low Weighted than GUI because it dose not need to translate to machine language.

ok so i make some changes, specific spell power and spell hashtable has been removed
and changed to one Hashtable and one Spell Power for all spells.
now i use handle specific id instead of specific spell variable.

is it a right way ?

  • Map init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set Spell_Table = (Last created hashtable)
  • AVG
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to AVG
    • Actions
      • Set AVG_Counter = (AVG_Counter + 1)
      • Hashtable - Save 200.00 as (Key avg) of (Key (Triggering unit)) in Spell_Table
      • Hashtable - Save 15.00 as (Key avg_time) of (Key (Triggering unit)) in Spell_Table
      • Unit Group - Add (Triggering unit) to AVG_UnitGroup
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • AVG_Counter Equal to 1
        • Then - Actions
          • Trigger - Turn on AVG Loop <gen>
        • Else - Actions
  • AVG Loop
    • Events
      • Time - Every 0.01 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in AVG_UnitGroup and do (Actions)
        • Loop - Actions
          • Set AVG_Timer = (Load (Key avg_time) of (Key (Picked unit)) from Spell_Table)
          • Hashtable - Save (AVG_Timer - 0.01) as (Key avg_time) of (Key (Picked unit)) in Spell_Table
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AVG_Timer Less than or equal to 0.00
            • Then - Actions
              • Set AVG_Counter = (AVG_Counter - 1)
              • Hashtable - Save ((Load (Key avg) of (Key (Picked unit)) from Spell_Table) - 200.00) as (Key avg) of (Key (Picked unit)) in Spell_Table
              • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in Spell_Table
              • Unit Group - Remove (Picked unit) from AVG_UnitGroup
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • AVG_Counter Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
            • Else - Actions
  • Heal
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Holy Light
    • Actions
      • Unit - Set life of (Target unit of ability being cast) to ((Life of (Target unit of ability being cast)) + (Load (Key avg) of (Key (Triggering unit)) from Spell_Table))
 
Level 15
Joined
Aug 14, 2007
Messages
936
@Alipresent Judging from what the codes say, they should work perfectly without any glitches but I want to focus on Triggering Unit for Heal ability. It is usually not a good practice to use Triggering Unit in many cases since sometimes they overlap one another, so please remember to use Casting Unit instead as that will eliminate any possible glitch that can happen.
 
Status
Not open for further replies.
Top