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

Genetic Shield v. 1.1

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
  • Like
Reactions: opiumwar
Hey everyone!

This spell may be known already but i wanted to test my knowledge in hashtables. Just to get ya to know that this is my first spell using hashtables =)

Here you have the tooltip below:

geneticshieldtooltip.png


v. 1.1 - [Fixed mayor bug reported by Anachron] - [Added some small new SFX]

v. 1.0 - [Created and Uploaded!]


and here you have the Code =)

  • GS Start
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Genetic Shield
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Target unit of ability being cast) is in GS_EventGroup) Equal to False
        • Then - Actions
          • Trigger - Add to GS Less Damage <gen> the event (Unit - (Target unit of ability being cast) Takes damage)
          • Unit Group - Add (Target unit of ability being cast) to GS_EventGroup
        • Else - Actions
      • Hashtable - Save 0.00 as (Key shield_damage) of (Key (Target unit of ability being cast)) in GS_Hashtable
      • Hashtable - Save 0 as (Key timer) of (Key (Target unit of ability being cast)) in GS_Hashtable
      • Hashtable - Save Handle Of(Target unit of ability being cast) as (Key hero) of (Key (Target unit of ability being cast)) in GS_Hashtable
      • Unit Group - Add (Target unit of ability being cast) to GS_Units
      • Trigger - Turn on GS Less Damage <gen>
      • Trigger - Turn on GS Timer <gen>
  • GS Less Damage
    • Events
    • Conditions
      • ((Triggering unit) has buff Genetic Shield ) Equal to True
    • Actions
      • Set GS_CurrentDamage = (Load (Key shield_damage) of (Key (Triggering unit)) from GS_Hashtable)
      • Unit - Set life of (Triggering unit) to ((Life of (Triggering unit)) + ((Damage taken) / (Real(2))))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • GS_CurrentDamage Greater than or equal to 250.00
        • Then - Actions
          • Special Effect - Create a special effect attached to the overhead of (Triggering unit) using Abilities\Spells\Undead\ReplenishMana\ReplenishManaCasterOverhead.mdl
          • Special Effect - Destroy (Last created special effect)
          • Set GS_Loc[1] = (Position of (Triggering unit))
          • Set GS_VictimGroup[1] = (Units within 500.00 of GS_Loc[1] matching ((((Matching unit) belongs to an enemy of (Owner of (Triggering unit))) Equal to True) and ((((Matching unit) is alive) Equal to True) and ((((Matching unit) is Magic Immune) Equal to False) and (((Matching unit) is
          • Unit Group - Pick every unit in GS_VictimGroup[1] and do (Actions)
            • Loop - Actions
              • Unit - Cause (Picked unit) to damage (Picked unit), dealing GS_CurrentDamage damage of attack type Spells and damage type Normal
              • Special Effect - Create a special effect attached to the chest of (Picked unit) using Abilities\Spells\Undead\DeathCoil\DeathCoilSpecialArt.mdl
              • Special Effect - Destroy (Last created special effect)
              • Set GS_Loc[2] = (Position of (Picked unit))
              • Set GS_Angle = (Angle from GS_Loc[1] to GS_Loc[2])
              • Hashtable - Save GS_Angle as (Key angle) of (Key (Picked unit)) in GS_Hashtable
              • Hashtable - Save 0.00 as (Key current_range) of (Key (Picked unit)) in GS_Hashtable
              • Custom script: call RemoveLocation (udg_GS_Loc[2])
          • Unit - Remove Genetic Shield buff from (Triggering unit)
          • Custom script: call RemoveLocation (udg_GS_Loc[1])
          • Unit Group - Remove (Triggering unit) from GS_Units
          • Hashtable - Clear all child hashtables of child (Key (Triggering unit)) in GS_Hashtable
          • Trigger - Turn on GS PushBack <gen>
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (GS_Units is empty) Equal to True
            • Then - Actions
              • Trigger - Turn off GS Timer <gen>
              • Trigger - Turn off (This trigger)
            • Else - Actions
        • Else - Actions
          • Set GS_CurrentDamage = (GS_CurrentDamage + (Damage taken))
          • Hashtable - Save GS_CurrentDamage as (Key shield_damage) of (Key (Triggering unit)) in GS_Hashtable
  • GS PushBack
    • Events
      • Time - Every 0.02 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in GS_VictimGroup[1] and do (Actions)
        • Loop - Actions
          • Set GS_CurrentRange = (Load (Key current_range) of (Key (Picked unit)) from GS_Hashtable)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • GS_CurrentRange Less than 100.00
            • Then - Actions
              • Set GS_Loc[3] = (Position of (Picked unit))
              • Set GS_Angle = (Load (Key angle) of (Key (Picked unit)) from GS_Hashtable)
              • Set GS_Loc[4] = (GS_Loc[3] offset by 10.00 towards GS_Angle degrees)
              • Unit - Move (Picked unit) instantly to GS_Loc[4]
              • Custom script: call RemoveLocation (udg_GS_Loc[3])
              • Custom script: call RemoveLocation (udg_GS_Loc[4])
              • Set GS_CurrentRange = (GS_CurrentRange + 10.00)
              • Hashtable - Save GS_CurrentRange as (Key current_range) of (Key (Picked unit)) in GS_Hashtable
            • Else - Actions
              • Unit Group - Remove (Picked unit) from GS_VictimGroup[1]
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ((Picked unit) is A Hero) Equal to False
                  • (Percentage life of (Picked unit)) Less than or equal to 15.00
                • Then - Actions
                  • Set GS_Loc[5] = (Position of (Picked unit))
                  • Set GS_VictimGroup[2] = (Units within 200.00 of GS_Loc[5] matching ((((Matching unit) belongs to an enemy of (Owner of (Load (Key hero) of (Key (Picked unit)) in GS_Hashtable))) Equal to True) and ((((Matching unit) is alive) Equal to True) and ((((Matching unit) is Magic Immune) Eq
                  • Set GS_Damage = ((Percentage life of (Picked unit)) / (Real(2)))
                  • Unit Group - Pick every unit in GS_VictimGroup[2] and do (Actions)
                    • Loop - Actions
                      • Unit - Cause (Picked unit) to damage (Picked unit), dealing GS_Damage damage of attack type Spells and damage type Normal
                      • Special Effect - Create a special effect attached to the head of (Picked unit) using Abilities\Spells\Other\ImmolationRed\ImmolationRedDamage.mdl
                      • Special Effect - Destroy (Last created special effect)
                  • Special Effect - Create a special effect attached to the chest of (Picked unit) using Abilities\Spells\Other\Doom\DoomDeath.mdl
                  • Special Effect - Destroy (Last created special effect)
                  • Unit - Kill (Picked unit)
                  • Custom script: call RemoveLocation (udg_GS_Loc[5])
                  • Custom script: call DestroyGroup (udg_GS_VictimGroup[2])
                • Else - Actions
              • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in GS_Hashtable
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (GS_VictimGroup[1] is empty) Equal to True
        • Then - Actions
          • Hashtable - Clear all child hashtables of child (Key (Target unit of ability being cast)) in GS_Hashtable
          • Custom script: call DestroyGroup (udg_GS_VictimGroup[1])
          • Trigger - Turn off (This trigger)
        • Else - Actions
  • GS Timer
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in GS_Units and do (Actions)
        • Loop - Actions
          • Set GS_Timer = (Load (Key timer) of (Key (Picked unit)) from GS_Hashtable)
          • Set GS_CurrentDamage = (Load (Key shield_damage) of (Key (Picked unit)) from GS_Hashtable)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • GS_Timer Equal to 14
            • Then - Actions
              • Special Effect - Create a special effect attached to the overhead of (Picked unit) using Abilities\Spells\Undead\ReplenishMana\ReplenishManaCasterOverhead.mdl
              • Special Effect - Destroy (Last created special effect)
              • Set GS_Loc[6] = (Position of (Picked unit))
              • Set GS_VictimGroup[1] = (Units within 500.00 of GS_Loc[6] matching ((((Matching unit) belongs to an enemy of (Owner of (Picked unit))) Equal to True) and ((((Matching unit) is alive) Equal to True) and ((((Matching unit) is Magic Immune) Equal to False) and (((Matching unit) is A gr
              • Unit Group - Pick every unit in GS_VictimGroup[1] and do (Actions)
                • Loop - Actions
                  • Unit - Cause (Picked unit) to damage (Picked unit), dealing GS_CurrentDamage damage of attack type Spells and damage type Normal
                  • Special Effect - Create a special effect attached to the chest of (Picked unit) using Abilities\Spells\Undead\DeathCoil\DeathCoilSpecialArt.mdl
                  • Special Effect - Destroy (Last created special effect)
                  • Set GS_Loc[7] = (Position of (Picked unit))
                  • Set GS_Angle = (Angle from GS_Loc[6] to GS_Loc[7])
                  • Hashtable - Save GS_Angle as (Key angle) of (Key (Picked unit)) in GS_Hashtable
                  • Hashtable - Save 0.00 as (Key current_range) of (Key (Picked unit)) in GS_Hashtable
                  • Custom script: call RemoveLocation (udg_GS_Loc[7])
              • Unit - Remove Genetic Shield buff from (Picked unit)
              • Custom script: call RemoveLocation (udg_GS_Loc[6])
              • Unit Group - Remove (Picked unit) from GS_Units
              • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in GS_Hashtable
              • Trigger - Turn on GS PushBack <gen>
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (GS_Units is empty) Equal to True
                • Then - Actions
                  • Trigger - Turn off GS Less Damage <gen>
                  • Trigger - Turn off (This trigger)
                • Else - Actions
            • Else - Actions
              • Set GS_Timer = (GS_Timer + 1)
              • Hashtable - Save GS_Timer as (Key timer) of (Key (Picked unit)) in GS_Hashtable
Hopes you like this spell and tell me if you find it Non-MUI, leaks or lags.


Keywords:
Shield, Genetic, Green, tjordell, svenskunganka, block, damage, less damage, armor,
Contents

Genetic Shield (Map)

Reviews
12th Dec 2015 IcemanBo: Too long time as NeedsFix. Rejected. 01:01, 24th Jun 2010 The_Reborn_Devil: You should store units like "Triggering unit", "Target unit of ability being cast" and "Picked unit" in variables as you seem to use those a...

Moderator

M

Moderator

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

01:01, 24th Jun 2010
The_Reborn_Devil:

You should store units like "Triggering unit", "Target unit of ability being cast" and "Picked unit" in variables as you seem to use those a lot. Storing them in variables will increase the efficiency of your spell.
Timers with intervals at 0.02 is not good and I would recommend using intervals at 0.04. Movement will still be smooth with that interval and too fast intervals can cause lag.


Status: Rejected until updated
Rating: N/A

PM me or another mod once you've updated this to get it reviewed again. Have a nice day!
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,180
Your spell bugs under multiple circamstances.

Firstly if a unit with the shield (fully charges) having 50 HP (max and at 100% current life) was to take 98 damage the unit would die when acording to the tooltip it should only take 49 damage and live. Secondly if a unit is at full health like 1000 and takes 10 damage, he will have 990 life instead of the 995 the tool tip tells you he should have (0% absorbed).

Remember that the event fires before the actual damage is done and removed from the units health.

Also remember all spells must have mutli level support (forgive me if it does but a quick glance at the triggers does not show it does).
 
Level 11
Joined
Jan 25, 2009
Messages
572
Dr Super Good, That was wierd... I will have a further look into this...

EDIT: Well for me it works for how many units as possible. This is MUI. Try it you'rself. And also the damage, I'm 80% sure that it works. Take a further look into this please. Thanks a lot for taking time.
 
Level 11
Joined
Jan 25, 2009
Messages
572
Easier to calc with 0.02 instead of 0.03 and the reason why 0.02 doesn't work is because the human brain can only hanlde 1 picture every 0.028... something i think. Thats why moste of the peoples uses 0.03 but i find that har to calculate with cause there wont be any exact number when calculating.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,180
Easier to calc with 0.02 instead of 0.03 and the reason why 0.02 doesn't work is because the human brain can only hanlde 1 picture every 0.028... something i think. Thats why moste of the peoples uses 0.03 but i find that har to calculate with cause there wont be any exact number when calculating.

Total nonsense...
The average computer display has a 60 frame per second update. WC3 is designed with this in mind meaning the default is 60 frames per second or 1 frame every 0.01666....... seconds. As such moving stuff every 0.01 seconds would result in it moving more than the number of frames that get displayed. 0.02 is pretty close to the real value and works at 50 frames per second, it is better to not update it every frame than to update it more than once a frame. Finally people use 0.03 seconds per frame because that is very close to NTSC update which people are used to (slightly more than 30 frames per second). However it is noticable that it is not as smooth as 0.02 or 0.01 updates persecond.

The human eye is not a camera, it is a sensor. This means that it generates near constant signals to your brain. It is reconed as such that the human eye can pick up the difference of up to 200 frames per second although the exposure of each frame then is as such that your brain will not be able to process it fully (you can not read 200 pages a second but can notice movement for 200 frames a second).

Firstly if a unit with the shield (fully charges) having 50 HP (max and at 100% current life) was to take 98 damage the unit would die when acording to the tooltip it should only take 49 damage and live. Secondly if a unit is at full health like 1000 and takes 10 damage, he will have 990 life instead of the 995 the tool tip tells you he should have (0% absorbed).

Remember that the event fires before the actual damage is done and removed from the units health.
Please read...
I did not even have to test your spell to spot that problem because you are not the only person who has tried damage absorption via triggers. Unless blizzard has changed this in the last patch (which I highly doubt) there is no way what you are doing works properly (the bugs mentioned should occur).

Lets run the case of a unit with 50 max life taking 98 damage.
Firstly the event runs.
You then reheal the unit 49 hitpoints thus 50+49 = 99. As the units max life is 50 however this means the units health is rehealed to 50 cause life can not exceed max life in my experience.
The unit then takes 98 damage but as 50 - 98 = -48, the unit is dead cause it is less than the death threshold.

Like wise with the case of a 1000 hitpoint unit taking 10 damage.
Firstly the event runs.
You then reheal the unit by 5 so 1000+5 = 1005. However the max life is 1000 thus the life clips to 1000.
The unit then takes the damage (10) thus 1000-10 = 990.

Both these cases demonstrate bugs in your current coding which can have fatal or irritating consequences.

I do agree that in the case of a unit with 500/1000 health taking 10 damage it will work fine, but in the case of a unit taking more damage than max health or having full health it will not work fine as I have practicle experience with the method you used doing this in my own spell. The work around requires heavy coding with a 0 expiration timer so that it runs near imediatly and requires the use of +max life abilities so that you can actually set the life correctly after the damage is dealt to the unit not before (like the event does).

Once again, the event is run before the damage is actually dealt to the unit so as soon as the actions of the trigger are done, the unit then has the damage dealt to its health.

Also hows multi level support?
 
Top