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

GUI Dark Shackle V1.4

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
Sends out a chain with a sharp end that pulls and cripples the first unit it hits.

Indexing system by Hanky
ChainHead model by Infrisios
Fatal Wound Model by me.




  • DSCONFIG
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- This serves as storage for the 2d arrays --------
      • Hashtable - Create a hashtable
      • Set DS_HASHTABLE = (Last created hashtable)
      • -------- This stores the spell. --------
      • Set DS_ABILITY = Dark Shackle
      • -------- The special effect that appears when a unit is pulled. --------
      • Set DS_SPFX = war3mapImported\BleedEffect.mdx
      • -------- The type of unit created and will also serve as dummy units --------
      • Set DS_DUMMYHEAD_TYPE = DARK SHACKLE DUMMY HEAD
      • Set DS_DUMMYTAIL_TYPE = DARK SHACKLE DUMMY TAIL
      • -------- The spell's maximum distance to be travelled --------
      • Set DS_MAX_DISTANCE[1] = 600.00
      • Set DS_MAX_DISTANCE[2] = 800.00
      • Set DS_MAX_DISTANCE[3] = 1000.00
      • Set DS_MAX_DISTANCE[4] = 1200.00
      • -------- The spell's AoE --------
      • Set DS_AOE[1] = 100.00
      • Set DS_AOE[2] = 100.00
      • Set DS_AOE[3] = 100.00
      • Set DS_AOE[4] = 100.00
      • -------- The spell's impact damage. --------
      • Set DS_DAMAGE[1] = 60.00
      • Set DS_DAMAGE[2] = 120.00
      • Set DS_DAMAGE[3] = 180.00
      • Set DS_DAMAGE[4] = 240.00
      • -------- The hook's travel speed. --------
      • Set DS_SPEED[1] = 2000.00
      • Set DS_SPEED[2] = 2000.00
      • Set DS_SPEED[3] = 2000.00
      • Set DS_SPEED[4] = 2000.00



  • DSSTART
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to DS_ABILITY
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DS_INDEX_LISTENER Equal to 0
        • Then - Actions
          • Trigger - Turn on DSLOOP <gen>
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DS_RECYCLE_SIZE Greater than 0
        • Then - Actions
          • Set DS_RECYCLE_SIZE = (DS_RECYCLE_SIZE - 1)
          • Set DS_CURRENT_INDEX = DS_CONTAINER[DS_RECYCLE_SIZE]
        • Else - Actions
          • Set DS_CURRENT_INDEX = DS_INDEX_SIZE
          • Set DS_INDEX_SIZE = (DS_INDEX_SIZE + 1)
      • -------- IMPORTANT VARIABLES --------
      • Set DS_DISTANCE_TRAVELLED[DS_CURRENT_INDEX] = 0.00
      • Set DS_TRIGGER_UNIT[DS_CURRENT_INDEX] = (Triggering unit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Target unit of ability being cast) Equal to No unit
        • Then - Actions
          • Set DS_ANGLE[DS_CURRENT_INDEX] = (Angle from (Position of (Triggering unit)) to (Target point of ability being cast))
        • Else - Actions
          • Set DS_ANGLE[DS_CURRENT_INDEX] = (Angle from (Position of (Triggering unit)) to (Position of (Target unit of ability being cast)))
      • Unit - Create 1 DS_DUMMYHEAD_TYPE for (Owner of DS_TRIGGER_UNIT[DS_CURRENT_INDEX]) at (Position of DS_TRIGGER_UNIT[DS_CURRENT_INDEX]) facing DS_ANGLE[DS_CURRENT_INDEX] degrees
      • Set DS_DUMMY_HEAD[DS_CURRENT_INDEX] = (Last created unit)
      • Set DS_PULLED_A_UNIT[DS_CURRENT_INDEX] = False
      • Set DS_LEVEL_OF_ABILITY[DS_CURRENT_INDEX] = (Level of DS_ABILITY for (Triggering unit))
      • Set DS_TRAVEL_SPEED[DS_CURRENT_INDEX] = DS_SPEED[DS_LEVEL_OF_ABILITY[DS_CURRENT_INDEX]]
      • Set DS_TEMPLOC1 = (Position of DS_DUMMY_HEAD[DS_CURRENT_INDEX])
      • Set DS_TEMPLOC2 = (DS_TEMPLOC1 offset by (0.03 x DS_TRAVEL_SPEED[DS_CURRENT_INDEX]) towards DS_ANGLE[DS_CURRENT_INDEX] degrees)
      • Custom script: call RemoveLocation(udg_DS_TEMPLOC1)
      • Custom script: call RemoveLocation(udg_DS_TEMPLOC2)
      • -------- IMPORTANT SYSTEM PART START --------
      • Set DS_INDEX_CONTAINER[DS_INDEX_LISTENER] = DS_CURRENT_INDEX
      • Set DS_INDEX_LISTENER = (DS_INDEX_LISTENER + 1)



  • DSLOOP
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer DARK_SHACKLE_EXAMPLE_LOOP) from 0 to (DS_INDEX_LISTENER - 1), do (Actions)
        • Loop - Actions
          • -------- Set the current index --------
          • Set DS_CURRENT_INDEX = DS_INDEX_CONTAINER[DARK_SHACKLE_EXAMPLE_LOOP]
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • DS_PULLED_A_UNIT[DS_CURRENT_INDEX] Equal to False
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • DS_DISTANCE_TRAVELLED[DS_CURRENT_INDEX] Less than DS_MAX_DISTANCE[DS_LEVEL_OF_ABILITY[DS_CURRENT_INDEX]]
                • Then - Actions
                  • -------- This simulates the Hook head's movement. --------
                  • Set DS_TEMPLOC1 = (Position of DS_DUMMY_HEAD[DS_CURRENT_INDEX])
                  • Set DS_TEMPLOC2 = (DS_TEMPLOC1 offset by (0.03 x DS_TRAVEL_SPEED[DS_CURRENT_INDEX]) towards DS_ANGLE[DS_CURRENT_INDEX] degrees)
                  • Unit - Move DS_DUMMY_HEAD[DS_CURRENT_INDEX] instantly to DS_TEMPLOC2
                  • -------- This creates "dummy" tails. --------
                  • Unit - Create 1 DS_DUMMYTAIL_TYPE for (Owner of DS_TRIGGER_UNIT[DS_CURRENT_INDEX]) at DS_TEMPLOC1 facing DS_ANGLE[DS_CURRENT_INDEX] degrees
                  • Unit Group - Add (Last created unit) to DS_DUMMY_UNITS[DS_CURRENT_INDEX]
                  • -------- It is then registered in the Hashtable; It's own unique index wil be useful later when it travels back to its point of origin. --------
                  • Set DS_DUMMY_UNIT_COUNT[DS_CURRENT_INDEX] = (Number of units in DS_DUMMY_UNITS[DS_CURRENT_INDEX])
                  • -------- I used hashtables because the spell needs 2D arrays. --------
                  • Hashtable - Save Handle Of(Last created unit) as DS_DUMMY_UNIT_COUNT[DS_CURRENT_INDEX] of DS_CURRENT_INDEX in DS_HASHTABLE
                  • Custom script: call RemoveLocation(udg_DS_TEMPLOC1)
                  • Custom script: call RemoveLocation(udg_DS_TEMPLOC2)
                  • -------- Makes the chain follow the caster --------
                  • For each (Integer DS_GEN_LOOPER) from 1 to DS_DUMMY_UNIT_COUNT[DS_CURRENT_INDEX], do (Actions)
                    • Loop - Actions
                      • Set DS_TEMPLOC1 = (Position of DS_TRIGGER_UNIT[DS_CURRENT_INDEX])
                      • Set DS_TEMPLOC2 = (Position of DS_DUMMY_HEAD[DS_CURRENT_INDEX])
                      • Set DS_TEMP_REAL_X = (Distance between DS_TEMPLOC1 and DS_TEMPLOC2)
                      • Set DS_TEMP_REAL_Y = ((Real(DS_GEN_LOOPER)) / (Real(DS_DUMMY_UNIT_COUNT[DS_CURRENT_INDEX])))
                      • Set DS_TEMP_REAL_Z = (DS_TEMP_REAL_Y x DS_TEMP_REAL_X)
                      • Set DS_TEMP_REAL_X = (Angle from DS_TEMPLOC1 to DS_TEMPLOC2)
                      • Custom script: call RemoveLocation(udg_DS_TEMPLOC1)
                      • Custom script: call RemoveLocation(udg_DS_TEMPLOC2)
                      • Set DS_TEMPLOC1 = (Position of DS_TRIGGER_UNIT[DS_CURRENT_INDEX])
                      • Set DS_TEMPLOC2 = (DS_TEMPLOC1 offset by DS_TEMP_REAL_Z towards DS_TEMP_REAL_X degrees)
                      • Set DS_DUMMY_TAIL = (Load DS_GEN_LOOPER of DS_CURRENT_INDEX in DS_HASHTABLE)
                      • Unit - Move DS_DUMMY_TAIL instantly to DS_TEMPLOC2, facing DS_TEMP_REAL_X degrees
                      • Custom script: call RemoveLocation(udg_DS_TEMPLOC1)
                      • Custom script: call RemoveLocation(udg_DS_TEMPLOC2)
                  • -------- This serves as a substitute for "Pick every unit in etc..." --------
                  • Set DS_POSSIBLE_TARGETS[DS_CURRENT_INDEX] = (Units within DS_AOE[DS_LEVEL_OF_ABILITY[DS_CURRENT_INDEX]] of (Position of DS_DUMMY_HEAD[DS_CURRENT_INDEX]) matching ((((Matching unit) is A structure) Equal to False) and ((((Matching unit) is Magic Immune) Equal to False) and ((((Matching unit) is A flying
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (DS_POSSIBLE_TARGETS[DS_CURRENT_INDEX] is empty) Equal to False
                    • Then - Actions
                      • Set DS_PULLED_UNIT[DS_CURRENT_INDEX] = (Random unit from DS_POSSIBLE_TARGETS[DS_CURRENT_INDEX])
                      • -------- This condition makes sure that the spell only damages enemies. --------
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (DS_PULLED_UNIT[DS_CURRENT_INDEX] belongs to an enemy of (Owner of DS_TRIGGER_UNIT[DS_CURRENT_INDEX])) Equal to True
                        • Then - Actions
                          • Unit - Cause DS_TRIGGER_UNIT[DS_CURRENT_INDEX] to damage DS_PULLED_UNIT[DS_CURRENT_INDEX], dealing DS_DAMAGE[DS_LEVEL_OF_ABILITY[DS_CURRENT_INDEX]] damage of attack type Hero and damage type Unknown
                        • Else - Actions
                          • -------- If it hit an enemy, it travels back to its point of origin. --------
                      • Set DS_PULLED_A_UNIT[DS_CURRENT_INDEX] = True
                    • Else - Actions
                  • Custom script: set udg_DS_POSSIBLE_TARGETS[udg_DS_CURRENT_INDEX]=null
                  • Set DS_DISTANCE_TRAVELLED[DS_CURRENT_INDEX] = (DS_DISTANCE_TRAVELLED[DS_CURRENT_INDEX] + (0.03 x DS_TRAVEL_SPEED[DS_CURRENT_INDEX]))
                • Else - Actions
                  • Set DS_DISTANCE_TRAVELLED[DS_CURRENT_INDEX] = 0.00
                  • -------- If it has reached the max distance, it travels back to its point of origin. --------
                  • Set DS_PULLED_A_UNIT[DS_CURRENT_INDEX] = True
            • Else - Actions
              • -------- Makes the chain follow the caster --------
              • For each (Integer DS_GEN_LOOPER) from 1 to DS_DUMMY_UNIT_COUNT[DS_CURRENT_INDEX], do (Actions)
                • Loop - Actions
                  • Set DS_TEMPLOC1 = (Position of DS_TRIGGER_UNIT[DS_CURRENT_INDEX])
                  • Set DS_TEMPLOC2 = (Position of DS_DUMMY_HEAD[DS_CURRENT_INDEX])
                  • Set DS_TEMP_REAL_X = (Distance between DS_TEMPLOC1 and DS_TEMPLOC2)
                  • Set DS_TEMP_REAL_Y = ((Real(DS_GEN_LOOPER)) / (Real(DS_DUMMY_UNIT_COUNT[DS_CURRENT_INDEX])))
                  • Set DS_TEMP_REAL_Z = (DS_TEMP_REAL_Y x DS_TEMP_REAL_X)
                  • Set DS_TEMP_REAL_X = (Angle from DS_TEMPLOC1 to DS_TEMPLOC2)
                  • Custom script: call RemoveLocation(udg_DS_TEMPLOC1)
                  • Custom script: call RemoveLocation(udg_DS_TEMPLOC2)
                  • Set DS_TEMPLOC1 = (Position of DS_TRIGGER_UNIT[DS_CURRENT_INDEX])
                  • Set DS_TEMPLOC2 = (DS_TEMPLOC1 offset by DS_TEMP_REAL_Z towards DS_TEMP_REAL_X degrees)
                  • Set DS_DUMMY_TAIL = (Load DS_GEN_LOOPER of DS_CURRENT_INDEX in DS_HASHTABLE)
                  • Unit - Move DS_DUMMY_TAIL instantly to DS_TEMPLOC2, facing DS_TEMP_REAL_X degrees
                  • Custom script: call RemoveLocation(udg_DS_TEMPLOC1)
                  • Custom script: call RemoveLocation(udg_DS_TEMPLOC2)
              • Set DS_DUMMY_UNIT_COUNT[DS_CURRENT_INDEX] = (Number of units in DS_DUMMY_UNITS[DS_CURRENT_INDEX])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • DS_DUMMY_UNIT_COUNT[DS_CURRENT_INDEX] Greater than 0
                • Then - Actions
                  • -------- The special effect that appears when a unit gets pulled. --------
                  • Special Effect - Create a special effect attached to the chest of DS_PULLED_UNIT[DS_CURRENT_INDEX] using DS_SPFX
                  • Special Effect - Destroy (Last created special effect)
                  • -------- This is where the 2D arrays come in handy. With their own unique index, the Hook 'head' travels back to its origin point by tracing the 'last created unit' in the DS_DUMMY_UNITS --------
                  • Set DS_DUMMY_TAIL = (Load DS_DUMMY_UNIT_COUNT[DS_CURRENT_INDEX] of DS_CURRENT_INDEX in DS_HASHTABLE)
                  • Set DS_TEMPLOC1 = (Position of DS_DUMMY_TAIL)
                  • Unit - Move DS_DUMMY_HEAD[DS_CURRENT_INDEX] instantly to DS_TEMPLOC1
                  • Unit - Move DS_PULLED_UNIT[DS_CURRENT_INDEX] instantly to DS_TEMPLOC1
                  • Unit - Remove DS_DUMMY_TAIL from the game
                  • Custom script: call RemoveLocation(udg_DS_TEMPLOC1)
                • Else - Actions
                  • -------- This is the slowing effect. Modify it as you wish. I am quite sure everyone is familiar with this. --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (DS_PULLED_UNIT[DS_CURRENT_INDEX] belongs to an enemy of (Owner of DS_TRIGGER_UNIT[DS_CURRENT_INDEX])) Equal to True
                    • Then - Actions
                      • Unit - Create 1 DUMMY CASTER for (Owner of DS_TRIGGER_UNIT[DS_CURRENT_INDEX]) at (Position of DS_PULLED_UNIT[DS_CURRENT_INDEX]) facing Default building facing degrees
                      • Unit - Add Dark Shackle Slow to (Last created unit)
                      • Unit - Set level of Dark Shackle Slow for (Last created unit) to DS_LEVEL_OF_ABILITY[DS_CURRENT_INDEX]
                      • Unit - Order (Last created unit) to Undead Necromancer - Cripple DS_PULLED_UNIT[DS_CURRENT_INDEX]
                      • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
                    • Else - Actions
                  • -------- The following actions destroy the used variables --------
                  • Unit - Remove DS_DUMMY_HEAD[DS_CURRENT_INDEX] from the game
                  • Set DS_DUMMY_HEAD[DS_CURRENT_INDEX] = No unit
                  • Set DS_TRIGGER_UNIT[DS_CURRENT_INDEX] = No unit
                  • Set DS_PULLED_A_UNIT[DS_CURRENT_INDEX] = False
                  • Set DS_PULLED_UNIT[DS_CURRENT_INDEX] = No unit
                  • Unit Group - Remove all units of DS_DUMMY_UNITS[DS_CURRENT_INDEX] from DS_DUMMY_UNITS[DS_CURRENT_INDEX]
                  • -------- IMPORTANT SYSTEM PART START --------
                  • -------- Decrease the normal index container size --------
                  • Set DS_INDEX_LISTENER = (DS_INDEX_LISTENER - 1)
                  • -------- Exchange the data from the last index to the current index --------
                  • Set DS_INDEX_CONTAINER[DARK_SHACKLE_EXAMPLE_LOOP] = DS_INDEX_CONTAINER[DS_INDEX_LISTENER]
                  • -------- Add an index to the Recycle Container --------
                  • Set DS_CONTAINER[DS_RECYCLE_SIZE] = DS_CURRENT_INDEX
                  • -------- Recycle Container Index Size gets increased --------
                  • Set DS_RECYCLE_SIZE = (DS_RECYCLE_SIZE + 1)
                  • -------- Reset Loop --------
                  • Set DARK_SHACKLE_EXAMPLE_LOOP = (DARK_SHACKLE_EXAMPLE_LOOP - 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • DS_INDEX_LISTENER Equal to 0
                    • Then - Actions
                      • Trigger - Turn off DSLOOP <gen>
                      • Skip remaining actions
                    • Else - Actions
                  • -------- IMPORTANT SYSTEM PART END --------





-Now only uses one hashtable
-Travel speed is now constant
-Fixed the location leaks
-Added new actions to the DSLOOP trigger: The chain now follows the caster.


Keywords:
hook,meat hook,meat,thresh,death,sentence,death sentence,pull,chain
Contents

cotd333's Dark Shackle (Map)

Reviews
12th Dec 2015 IcemanBo: Too long as NeedsFix. Rejected. 20:29, 1st Jan 2014 Maker: The spell has location leaks.

Moderator

M

Moderator

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

20:29, 1st Jan 2014
Maker: The spell has location leaks.
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
Things That Leak

  • Hashtable - Create a hashtable
Use one global hashtable for all instances, instead of creating one per cast.
  • 0.03 x DS_SPEED[DS_LEVEL_OF_ABILITY[DS_CURRENT_INDEX]]
this value is constant for a unit, calculate it once on spell cast.

These lines are useless. 0.00 is a normal real value, just as 1,35678 is.
  • Set DS_ANGLE[DS_CURRENT_INDEX] = 0.00
  • Set DS_DISTANCE_TRAVELLED[DS_CURRENT_INDEX] = 0.00
  • Set DS_LEVEL_OF_ABILITY[DS_CURRENT_INDEX] = 0
You may want to look into this.
Psycho Hook
 
Last edited:
Level 19
Joined
Mar 18, 2012
Messages
1,716
  • Unit - Move DS_PULLED_UNIT[DS_CURRENT_INDEX] instantly to (Position of DS_DUMMY_HEAD[DS_CURRENT_INDEX])
leaks location
  • Set DS_ANGLE[DS_CURRENT_INDEX] = (Angle from (Position of (Triggering unit)) to (Target point of ability being cast))
  • Else - Actions
  • Set DS_ANGLE[DS_CURRENT_INDEX] = (Angle from (Position of (Triggering unit)) to (Position of (Target unit of ability being cast)))
also here two (four) location leaks

  • 0.03 x DS_TRAVEL_SPEED[DS_CURRENT_INDEX]
you could do this math once on spell cast. 0.03 x speed[index] and save it to a D_TRAVEL_SPEED[index]
 
Level 13
Joined
Mar 29, 2012
Messages
530

REVIEW|GUI Dark Shackle|v1.4

Resource Status: Needs Fix
Rating: 2/5

GENERAL
  • You leaking head dummy spawn location. Use DS_TEMPLOC1 as the spawn location and of course remove that location after used
  • Another location leak, when picking possible targets, store the location in a variable
  • Last location leak, at the end of the spell, when creating the caster dummy
  • Destroy DS_POSSIBLE_TARGETS group
  • Make attack-type and damage-type configurable
PROS
  • MUI
  • Import instruction
CONS
  • Too much removing location actions (this could be reduced)
  • Less efficiency
SUGGESTIONS
  • Try using call SetUnitX/Y to move a unit, it's perform quite faster
[/TD][/tr]
If you have any question about this review, PM or VM me Review template by Doomlord
 
Top