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

Neather Ball 1.2a

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
I like making fancy spells but I only recently got to know how hash tables work so previously I had no chance getting my spells approved.

This is a spell based on trigonometry (sin, con, tan, ect.). I making a spell that would follow a sine-wave like so:
Sinuskurve01.gif


It's a little more advanced math than the usual but if used effectively, can be very pretty.

This spell contains 20+ variables so if you want to copy it into your map go to ´´files´´ and select ´´preferences´´ and turn on ´´Automatically create unknown variables while pasting trigger data´´.

then you will only need to make 4 dummies and 1 spell (based on carrion swam).




*15-01-12*
- Changed some triggering requested from Magtheridon96.

*16-01-12*
- Chanced timer to 0.08 insted of 0.04 to reduce special effects.
- Chanced center effect.
- Updated Screenshot

*19-01-12*
- Chanced Timer to 0.03 insted of 0.08
- Replaced Special effect with units
- Updated Screenshot
- Chanced some trigger

*20-01-12*
- Made an intro in the map file
- made an turn on/off system so it will not effect the game with lag.
- changed the tooltip of the spell a little


Keywords:
neather, ball, green, poison, mist, blast, explotion, war.
Contents

Neather Ball (Map)

Reviews
12th Dec 2015 IcemanBo: Too long as NeedsFix. Rejected. Required changes: Add importing instructions into the map file Set constants in the NBHash and settings trigger (NBSpeed, NBAngleChange...) Suggested changes: You don't need...

Moderator

M

Moderator

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

Reviewed by Maker, Neather Ball v1.2a, Jan 28th 2012

Required changes:
  • Add importing instructions into the map file
  • Set constants in the NBHash and settings trigger (NBSpeed, NBAngleChange...)

Suggested changes:
  • You don't need NBBalls unit group variable. Use single unit variable, and load units into it one by one

Additionally I hope you simplify the math, since as far as I can tell there is a lighter solution.

Reviewed by Maker, Neather Ball v1.2, Jan 19th 2012

Required changes:
  • Add importing instructions into the map file
  • Set constants in the NBHash and settings trigger (NBSpeed, NBAngleChange...)
  • NBLoop should be initially off, and it should be turned off when there are no units to loop through

Suggested changes:
  • You don't need NBBalls unit group variable. Use single unit variable, and load units into it one by one
  • Make the tooltip look more like default Blizzard tooltip, list the damage per level for example
19 Jan 2012
Bribe: Rename your triggers so they are more exclusive to the spell itself, "Cast" and "Move" are not very specific names for your spell.

JASS:
 Hashtable - Save NBRemaningTime as 0 of (Key (Triggering unit)) in NBHashtable
 Hashtable - Save Handle OfNBDummy as 1 of (Key (Triggering unit)) in NBHashtable
 Hashtable - Save NBCollisionIndicator as 2 of (Key (Triggering unit)) in NBHashtable
 Hashtable - Save NBSpeed as 3 of (Key (Triggering unit)) in NBHashtable
 Hashtable - Save NBAngle as 4 of (Key (Triggering unit)) in NBHashtable
 Hashtable - Save NBAnglechange as 5 of (Key (Triggering unit)) in NBHashtable
 Hashtable - Save NBSpellLevel as 6 of (Key (Triggering unit)) in NBHashtable

Change that to:

JASS:
 @Set Int = (Key (Triggering unit))@
 Hashtable - Save NBRemaningTime as 0 of @Integer@ in NBHashtable
 Hashtable - Save Handle OfNBDummy as 1 of @Integer@ in NBHashtable
 Hashtable - Save NBCollisionIndicator as 2 of @Integer@ in NBHashtable
 Hashtable - Save NBSpeed as 3 of @Integer@ in NBHashtable
 Hashtable - Save NBAngle as 4 of @Integer@ in NBHashtable
 Hashtable - Save NBAnglechange as 5 of @Integer@ in NBHashtable
 Hashtable - Save NBSpellLevel as 6 of @Integer@ in NBHashtable

Same with:

JASS:
 @Set Integer = (Key (Picked unit)@
 Set NBDummy = (Load 1 of @Integer@) in NBHashtable)
 Set NBCollisionIndicator = (Load 2 of @Integer@ from NBHashtable)
 Set NBSpeed = (Load 3 of @Integer@ from NBHashtable)
 Set NBAngle = (Load 4 of @Integer@ from NBHashtable)
 Set NBAnglechange = (Load 5 of @Integer@ from NBHashtable)

If you'd like to know why, ask.

I still think there is too much effect spam in a very short amount of time, even at 0.08 seconds, especially when there are multiple units affected. I think it might be better to create dummy units with those effects on them, and move the dummy units around instead of destroying the effects all the time.
 
Code Comming right up:

  • NBHash and settings
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set NBHashtable = (Last created hashtable)
      • -------- --------
      • -------- Settings of damage, aoe, ect. --------
      • -------- --------
      • -------- Damage increase per level (0-X) --------
      • Set NBDamage = 100.00
      • -------- Wide of AoE damage and balls movement (175-300) --------
      • Set NBWide = 250.00
      • -------- Move Speed of the ball (15-30) --------
      • Set NBSpeedIncreae = 22.00
      • -------- Frequency (must be able to be devided by 180) --------
      • -------- Ex: 7,5, 10, 15 --------
      • -------- (Stick to thise numbers to make the ball more beautifull) --------
      • Set NBFrequency = 7.50
[triggerNBCast
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Neather Ball
Actions
Set NBCaster = (Casting unit)
Set NBIntCaster = (Key (Triggering unit))
Unit Group - Add NBCaster to NBGroup
Set NBRemaningTime = 3.70
Set NBStartPoint = (Position of NBCaster)
Set NBCollisionIndicator = 180.00
Set NBSpeed = 40.00
Set NBAnglechange = 0.00
Set NBCastPoint = (Target point of ability being cast)
Set NBAngle = (Angle from NBStartPoint to NBCastPoint)
Set NBSpellLevel = ((Real((Level of Neather Ball for NBCaster))) x NBDamage)
Unit - Create 1 Dummy (ball) for (Owner of NBCaster) at NBStartPoint facing NBAngle degrees
Set NBBalls[1] = (Last created unit)
Unit - Create 1 Dummy (ball) for (Owner of NBCaster) at NBStartPoint facing NBAngle degrees
Set NBBalls[2] = (Last created unit)
Unit - Create 1 Dummy (ball large) for (Owner of NBCaster) at NBStartPoint facing NBAngle degrees
Set NBBalls[3] = (Last created unit)
Unit - Create 1 NBDummy for (Owner of NBCaster) at NBStartPoint facing Default building facing degrees
Set NBDummy = (Last created unit)
Unit - Add a NBRemaningTime second Generic expiration timer to NBBalls[1]
Unit - Add a NBRemaningTime second Generic expiration timer to NBBalls[2]
Unit - Add a NBRemaningTime second Generic expiration timer to NBBalls[3]
Unit - Add a (NBRemaningTime + 1.00) second Generic expiration timer to NBDummy
Hashtable - Save NBRemaningTime as 0 of NBIntCaster in NBHashtable
Hashtable - Save Handle OfNBDummy as 1 of NBIntCaster in NBHashtable
Hashtable - Save NBCollisionIndicator as 2 of NBIntCaster in NBHashtable
Hashtable - Save NBSpeed as 3 of NBIntCaster in NBHashtable
Hashtable - Save NBAngle as 4 of NBIntCaster in NBHashtable
Hashtable - Save NBAnglechange as 5 of NBIntCaster in NBHashtable
Hashtable - Save NBSpellLevel as 6 of NBIntCaster in NBHashtable
Hashtable - Save Handle OfNBBalls[1] as 7 of NBIntCaster in NBHashtable
Hashtable - Save Handle OfNBBalls[2] as 8 of NBIntCaster in NBHashtable
Hashtable - Save Handle OfNBBalls[3] as 9 of NBIntCaster in NBHashtable
Trigger - Turn on NBLoop <gen>
Custom script: call RemoveLocation(udg_NBStartPoint)
Custom script: call RemoveLocation(udg_NBCastPoint)
[/trigger]
  • NBLoop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in NBGroup and do (Actions)
        • Loop - Actions
          • Set NBIntCaster = (Key (Picked unit))
          • Set NBRemaningTime = (Load 0 of NBIntCaster from NBHashtable)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • NBRemaningTime Greater than 0.00
            • Then - Actions
              • Set NBDummy = (Load 1 of NBIntCaster in NBHashtable)
              • Set NBCollisionIndicator = (Load 2 of NBIntCaster from NBHashtable)
              • Set NBSpeed = (Load 3 of NBIntCaster from NBHashtable)
              • Set NBAngle = (Load 4 of NBIntCaster from NBHashtable)
              • Set NBAnglechange = (Load 5 of NBIntCaster from NBHashtable)
              • Set NBBalls[1] = (Load 7 of NBIntCaster in NBHashtable)
              • Set NBBalls[2] = (Load 8 of NBIntCaster in NBHashtable)
              • Set NBBalls[3] = (Load 9 of NBIntCaster in NBHashtable)
              • -------- --------- --------
              • Set NBStartPoint = (Position of NBDummy)
              • Set NBPoint2 = (NBStartPoint offset by NBSpeed towards NBAngle degrees)
              • Set NBSinAC = ((Sin(NBAnglechange)) x NBWide)
              • Set NBDegree = (Atan2(NBSinAC, NBSpeed))
              • Set NBSpeed2 = (NBSpeed x NBSpeed)
              • Set NBWide2 = (NBSinAC x NBSinAC)
              • Set NBDistance = (Square root((NBWide2 + NBSpeed2)))
              • Set NBPoint1 = (NBStartPoint offset by NBDistance towards (NBDegree + NBAngle) degrees)
              • Set NBPoint3 = (NBStartPoint offset by NBDistance towards ((NBDegree x -1.00) + NBAngle) degrees)
              • Set NBCaster = (Picked unit)
              • Unit - Move NBBalls[1] instantly to NBPoint1
              • Unit - Move NBBalls[2] instantly to NBPoint3
              • Unit - Move NBBalls[3] instantly to NBPoint2
              • Hashtable - Save (NBAnglechange + NBFrequency) as 5 of (Key (Picked unit)) in NBHashtable
              • Hashtable - Save (NBSpeed + NBSpeedIncreae) as 3 of (Key (Picked unit)) in NBHashtable
              • Hashtable - Save (NBRemaningTime - 0.03) as 0 of (Key (Picked unit)) in NBHashtable
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • NBCollisionIndicator Equal to NBAnglechange
                • Then - Actions
                  • Set NBSpellLevel = (Load 6 of NBIntCaster from NBHashtable)
                  • Hashtable - Save (NBCollisionIndicator + 180.00) as 2 of (Key (Picked unit)) in NBHashtable
                  • Special Effect - Create a special effect at NBPoint3 using Objects\Spawnmodels\Undead\UCancelDeath\UCancelDeath.mdl
                  • Special Effect - Destroy (Last created special effect)
                  • Custom script: set bj_wantDestroyGroup = true
                  • Unit Group - Pick every unit in (Units within NBWide of NBPoint3 matching ((((Matching unit) belongs to an enemy of (Owner of NBCaster)) Equal to True) and (((Matching unit) is Magic Immune) Equal to False))) and do (Actions)
                    • Loop - Actions
                      • Unit - Cause NBCaster to damage (Picked unit), dealing NBSpellLevel damage of attack type Spells and damage type Normal
                • Else - Actions
              • Custom script: call RemoveLocation(udg_NBPoint1)
              • Custom script: call RemoveLocation(udg_NBPoint2)
              • Custom script: call RemoveLocation(udg_NBPoint3)
              • Custom script: call RemoveLocation(udg_NBStartPoint)
            • Else - Actions
              • Hashtable - Clear all child hashtables of child NBIntCaster in NBHashtable
              • Unit Group - Remove (Picked unit) from NBGroup
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Number of units in NBGroup) Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
 
Last edited:
Not bad actually.

Tips:

-
  • Set StartPoint1 = (Load 1 of (Key (Picked unit)) from hash)
  • Set StartPoint2 = (Load 2 of (Key (Picked unit)) from hash)
  • Set BOOM = (Load 3 of (Key (Picked unit)) from hash)
  • Set Speed = (Load 4 of (Key (Picked unit)) from hash)
  • Set Angle = (Load 5 of (Key (Picked unit)) from hash)
  • Set Anglechange = (Load 6 of (Key (Picked unit)) from hash)
You should move these to the inside of the if/then/else block because if RemainingTime turned out to be 0 or less, you'd have read from the hashtable for nothing.

-
  • Set damagedUnits = (Units within Bred of Point4 matching ((((Matching unit) belongs to an enemy of (Owner of Caster)) Equal to True) and (((Matching unit) is Magic Immune) Equal to False)))
  • Unit Group - Pick every unit in damagedUnits and do (Actions)
    • Loop - Actions
      • Unit - Cause Caster to damage (Picked unit), dealing Level damage of attack type Spells and damage type Normal
  • Custom script: call DestroyGroup(udg_damagedUnits)
->

  • Custom script: set bj_wantDestroyGroup = true
  • Unit Group - Pick every unit in (Units within Bred of Point4 matching ((((Matching unit) belongs to an enemy of (Owner of Caster)) Equal to True) and (((Matching unit) is Magic Immune) Equal to False))) and do (Actions)
    • Loop - Actions
      • Unit - Cause Caster to damage (Picked unit), dealing Level damage of attack type Spells and damage type Normal
-
  • Player - Turn Gives bounty On for Player 8 (Pink)
  • -------- --------
  • Camera - Apply Camera 001 <gen> for Player 1 (Red) over 0.00 seconds
  • Visibility - Disable fog of war
  • Visibility - Disable black mask
These shouldn't be inside the Spell's code. You should put them in some other trigger inside the Demo-map.
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
This isn't an official review

-I recommend you make the learn tooltip similar to default Blizzard abilities
-Separate map spesific and spell spesific initialization stuff
-Constants should be set in a init trigger, not in the cast trigger
-I would use 0.03 loop period instead of 0.04. 25 vs 33 updates per second does make a difference visually for me
-moveing (should be moving ;) trigger shouldn't be on all the time
-You load stuff in the looping trigger that you might not need (boom, angle...)
-Use less point variables. You are using six, but you need no more than 4
-Why do you store the coordinated, but not use them? You convert the coordinates into a location...just store the location
-x*x is faster than Pow(x,2)
-Remove invulnerability abil from the dummy, it has locust
-Set dummy death type to can't raise, does not decay
-Remove upgrades used from the dummies
 
This isn't an official review

√ -I recommend you make the learn tooltip similar to default Blizzard abilities
√ -Separate map spesific and spell spesific initialization stuff
√ -Constants should be set in a init trigger, not in the cast trigger
-I would use 0.03 loop period instead of 0.04. 25 vs 33 updates per second does make a difference visually for me
- - [it sure does but it is hard to figure out the time of the spell with 4 insted of 3]
-moveing (should be moving ;) trigger shouldn't be on all the time
- - [Texting errors are not my best site (next update)]
√ -You load stuff in the looping trigger that you might not need (boom, angle...)
-Use less point variables. You are using six, but you need no more than 4
-Why do you store the coordinated, but not use them? You convert the coordinates into a location...just store the location
-x*x is faster than Pow(x,2)
√ -Remove invulnerability abil from the dummy, it has locust
√ -Set dummy death type to can't raise, does not decay
√ -Remove upgrades used from the dummies

This is what i have been doing son't know if it is ok
 
Level 11
Joined
Mar 27, 2011
Messages
293
Simply my dear friend, my tip is for when your Nether Ball Damages Any unit, it is banned.

Tip:

Already played with a hero named Blood Mage in Warcraft III Reign of Chaos or the Frozen Throne?

JASS:
 If not Play with him and use the Banish Ability to see how this works.

 If Yes, the Ban I refer is this the Same Ability (Banish).
 
Level 11
Joined
Mar 27, 2011
Messages
293
Simply my dear friend, my tip is for when your Nether Ball Damages Any unit, it is banned.

Tip:

Already played with a hero named Blood Mage in Warcraft III Reign of Chaos or the Frozen Throne?

JASS:
 If not Play with him and use the Banish Ability to see how this works.

 If Yes, the Ban I refer is this the Same Ability (Banish).

JASS:
Add the effect I told you about?
 
Last edited by a moderator:
Level 37
Joined
Mar 6, 2006
Messages
9,240
This is how I would improve the code a bit.



  • NBHash and settings
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set NBHashtable = (Last created hashtable)
      • -------- --------
      • -------- Settings of damage, aoe, ect. --------
      • -------- --------
      • -------- Damage increase per level (0-X) --------
      • Set NBDamage = 100.00
      • -------- Wide of AoE damage and balls movement (175-300) --------
      • Set NBWide = 250.00
      • -------- Move Speed of the ball (15-30) --------
      • Set NBSpeedIncreae = 22.00
      • -------- Frequency (must be able to be devided by 180) --------
      • -------- Ex: 7,5, 10, 15 --------
      • -------- (Stick to thise numbers to make the ball more beautifull) --------
      • Set NBFrequency = 7.50
      • -------- -------------- --------
      • Set NBSpeed = 40.00
      • Set NBRemaningTime = 3.70

  • NBCast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Neather Ball
    • Actions
      • Set unit1 = (Casting unit)
      • Set int1 = (Key (Triggering unit))
      • Unit Group - Add unit1 to NBGroup
      • Set Point1 = (Position of unit1)
      • Set Point2 = (Target point of ability being cast)
      • Set real1 = (Angle from Point1 to Point2)
      • Set real2 = ((Real((Level of Neather Ball for unit1))) x NBDamage)
      • -------- --------
      • Unit - Create 1 Dummy (ball) for (Owner of unit1) at Point1 facing real1 degrees
      • Unit - Add a NBRemaningTime second Generic expiration timer to (Last created unit)
      • Hashtable - Save Handle Of(Last created unit) as 7 of int1 in NBHashtable
      • -------- --------
      • Unit - Create 1 Dummy (ball) for (Owner of unit1) at Point1 facing real1 degrees
      • Unit - Add a NBRemaningTime second Generic expiration timer to (Last created unit)
      • Hashtable - Save Handle Of(Last created unit) as 8 of int1 in NBHashtable
      • -------- --------
      • Unit - Create 1 Dummy (ball large) for (Owner of unit1) at Point1 facing real1 degrees
      • Unit - Add a NBRemaningTime second Generic expiration timer to (Last created unit)
      • Hashtable - Save Handle Of(Last created unit) as 9 of int1 in NBHashtable
      • -------- --------
      • Unit - Create 1 NBDummy for (Owner of unit1) at Point1 facing Default building facing degrees
      • Unit - Add a (NBRemaningTime + 1.00) second Generic expiration timer to (Last created unit)
      • Hashtable - Save Handle Of(Last created unit) as 1 of int1 in NBHashtable
      • -------- --------
      • Hashtable - Save NBRemaningTime as 0 of int1 in NBHashtable
      • Hashtable - Save NBSpeed as 3 of int1 in NBHashtable
      • Hashtable - Save real1 as 4 of int1 in NBHashtable
      • Hashtable - Save 0.00 as 5 of int1 in NBHashtable
      • Hashtable - Save real2 as 6 of int1 in NBHashtable
      • -------- --------
      • Trigger - Turn on NBLoop <gen>
      • Custom script: call RemoveLocation(udg_Point1)
      • Custom script: call RemoveLocation(udg_Point2)



  • NBLoop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in NBGroup and do (Actions)
        • Loop - Actions
          • Set unit1 = (Picked unit)
          • Custom script: set udg_int1 = GetHandleId(udg_unit1)
          • Set real1 = (Load 0 of int1 from NBHashtable)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • real1 Greater than 0.00
            • Then - Actions
              • Set unit2 = (Load 1 of int1 in NBHashtable)
              • -------- speed --------
              • Set real2 = (Load 3 of int1 from NBHashtable)
              • -------- moving angle --------
              • Set real3 = (Load 4 of int1 from NBHashtable)
              • -------- "phase" --------
              • Set real4 = (Load 5 of int1 from NBHashtable)
              • -------- --------- --------
              • Set real5 = (NBWide x (Sin(real4)))
              • -------- --------- --------
              • Set Point1 = (Position of unit2)
              • Set Point2 = (Point1 offset by real2 towards real3 degrees)
              • Custom script: call RemoveLocation(udg_Point1)
              • Set Point1 = (Point2 offset by real5 towards (real3 + 90.00) degrees)
              • Set Point3 = (Point2 offset by real5 towards (real3 - 90.00) degrees)
              • Unit - Move (Load 7 of int1 in NBHashtable) instantly to Point1
              • Unit - Move (Load 8 of int1 in NBHashtable) instantly to Point3
              • Unit - Move (Load 9 of int1 in NBHashtable) instantly to Point2
              • Hashtable - Save (real4 + NBFrequency) as 5 of int1 in NBHashtable
              • Hashtable - Save (real2 + NBSpeedIncreae) as 3 of int1 in NBHashtable
              • Hashtable - Save (real1 - 0.03) as 0 of int1 in NBHashtable
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • real4 Greater than or equal to 180.00
                • Then - Actions
                  • Set real2 = (Load 6 of int1 from NBHashtable)
                  • Hashtable - Save 0.00 as 5 of (Key (Picked unit)) in NBHashtable
                  • Special Effect - Create a special effect at Point2 using Objects\Spawnmodels\Undead\UCancelDeath\UCancelDeath.mdl
                  • Special Effect - Destroy (Last created special effect)
                  • Custom script: set bj_wantDestroyGroup = true
                  • Unit Group - Pick every unit in (Units within NBWide of Point2 matching ((((Matching unit) belongs to an enemy of (Owner of unit1)) Equal to True) and (((Matching unit) is Magic Immune) Equal to False))) and do (Actions)
                    • Loop - Actions
                      • Unit - Cause unit1 to damage (Picked unit), dealing real2 damage of attack type Spells and damage type Normal
                • Else - Actions
              • Custom script: call RemoveLocation(udg_Point1)
              • Custom script: call RemoveLocation(udg_Point2)
              • Custom script: call RemoveLocation(udg_Point3)
            • Else - Actions
              • Hashtable - Clear all child hashtables of child int1 in NBHashtable
              • Unit Group - Remove unit1 from NBGroup
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Number of units in NBGroup) Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions



I removed unneeded variables, moved configurables to the init trigger and simplified the unit position calculation.

http://www.hiveworkshop.com/forums/pastebin.php?id=ea0x25
 
Top