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

[Trigger] Check my spell please

Status
Not open for further replies.
Level 3
Joined
Feb 9, 2008
Messages
63
im making a spell thats supposed to look like geomancers (a dota hero) earthbind spell

heres my trigger
Net Cast
  • Events
  • Net Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Net
    • Actions
      • Set NetCaster = (Triggering unit)
      • Set NetDummy = Net Dummy
      • Set NetCasterPoint = (Position of NetCaster)
      • Set NetDummyPoint = (Target point of ability being cast)
      • Unit - Create 1 NetDummy for (Owner of NetCaster) at NetCasterPoint facing NetCasterPoint
      • Set Net = (Last created unit)
      • Set NetDistance = 0.00
      • Set NetSpeed = 30.00
      • Trigger - Turn on Net Loop <gen>
Net Loop
  • Net Loop
    • Events
      • Time - Every 0.02 seconds of game time
    • Conditions
    • Actions
      • Set NetAngle = (Angle from NetCasterPoint to NetDummyPoint)
      • Set NetDistance = (NetDistance + NetSpeed)
      • Set NetPoint = (NetCasterPoint offset by NetDistance towards NetAngle degrees)
      • Unit - Move Net instantly to NetPoint
      • Set NetArea = (Units within 500.00 of (Position of Net) 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 (Owner of NetCaster)) Equal to True) and (((Matching unit) belo
      • Unit Group - Pick every unit in NetArea and do (Actions)
        • Loop - Actions
          • Set Dummy = Net Dummy 2
          • Unit - Create 1 Dummy for (Owner of NetCaster) at (Position of (Picked unit)) facing (Position of (Picked unit))
          • Set Dummy2 = (Last created unit)
          • Unit - Add Test to Dummy2
          • Unit - Order Dummy2 to Orc Raider - Ensnare (Picked unit)
          • Unit - Add a 1.00 second Generic expiration timer to Dummy2
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • NetDistance Greater than or equal to 500.00
        • Then - Actions
          • Unit - Remove Net from the game
          • Custom script: call DestroyGroup(udg_NetArea)
          • Custom script: call RemoveLocation(udg_NetPoint)
          • Custom script: call RemoveLocation(udg_NetCasterPoint)
          • Custom script: call RemoveLocation(udg_NetDummyPoint)
          • Trigger - Turn off (This trigger)
        • Else - Actions
the purpose of the spell is to cast a net(NetDummy) from the caster and travel from the caster to the casting point and ensnare every enemy the net encounters

1. does it still leak?
2. i wanna know the holes in trigger and how to improve it, hope you can advice me
3. tell me if i need to post the spell if you need more info
4. thanks in advance
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
1. It doesn't leak, but can be greatly improved.
2. You want to snare every unit it encounters, or the units around the target point when it reaches it?

Reduce the loop to 0.03
 
Level 11
Joined
Jan 25, 2009
Messages
572
1. It doesn't leak, but can be greatly improved.
2. You want to snare every unit it encounters, or the units around the target point when it reaches it?

Reduce the loop to 0.03

Correct me if I'm wrong, was a long time ago I worked with the World Editor but isn't it leaking since he removes the locations and groups when the spell is finished?

He should remove the locations and groups when he's done with them. Which technically means at the end of the first IF/THEN/ELSE.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
You're right, i didn't notice they were inside the "Then" block. They should be outside, at the end of the trigger, or before setting a new value into them, or when they're no longer needed
 
Level 3
Joined
Feb 9, 2008
Messages
63
He should remove the locations and groups when he's done with them. Which technically means at the end of the first IF/THEN/ELSE.
you mean i should remove the leaks at the unit group loop?

2. You want to snare every unit it encounters, or the units around the target point when it reaches it?
Reduce the loop to 0.03
Yes i wanted the "net"(Net Dummy) to ensanre every unit it encounter along its path
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
1. Your trigger is not MUI. If some other unit cast the ability while the first one is being casted, it will mess up the variable values.

2. You can improve this a lot by avoiding those globals variables and turnint to local JASS instead. I know JASS seems "too hard" or "complex" for most, but it's really easy once you understand it.

3. You're leaking every 0.02 seconds, since you only clean the point when the Net distance is 500+, all the points before that remains as leaks.

4. Here. it's heavility commented and should work. It's leakless, and is WAAAAY better than GUI (what you have). It has no magic, it just improves what you did in GUI taking advange of some JASS features (like locals, and X/Y, and natives, etc.). It's also MUI (Doesn't matter how many units cast it at the same time).

Just read the green lines, wich are comments, so you can know what every line does. You'll notice they're really similar to GUI, in fact, it has almost the same actions.

This is to set up the ability when it's cast
JASS:
globals
    hashtable Hash = InitHashtable() // The Hashtable
    group Nets // The Unit Group of the Nets
endglobals

function Trig_Nest_Cast_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'ZZZZ' // The Ability Being Cast. Replace 'ZZZZ' with your "Earthbind" ability
endfunction

function Trig_Nest_Cast_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit() // The Triggering Unit
    local location Point = GetSpellTargetLoc() // The Target Point of Ability Being Cast
    local real Pointx = GetLocationX(Point) // The X of the Target Point of Ability Being Cast
    local real Pointy = GetLocationY(Point)// The Y of the Target Point of Ability Being Cast
    local unit Dummy = CreateUnit(GetTriggerPlayer(), 'xxxx', GetUnitX(u), GetUnitY(u), 0) // The Dummy. Replace 'xxxx' with the Raw ID of your Net Dummy
    local integer id = GetHandleId(Dummy) // The HandleId of the Dummy
    local integer AbLvl = GetUnitAbilityLevel(u, 'ZZZZ') // The Ability Level // Replace 'ZZZZ' with your EarthBind ability
    local real Distance = 200 + (AbLvl * 100) // Every level increases distance by 100, over a base of 200
    local real Speed = AbLvl * 10 // Every level increases speed by 10
    local real AoE = 100 + (AbLvl * 100)
    
    call SaveReal(Hash, id, 0, Pointx) // Saving X on the Dummy
    call SaveReal(Hash, id, 1, Pointy) // Saving Y on the Dummy
    call SaveReal(Hash, id, 2, Distance) // Saving Distance on the Dummy
    call SaveReal(Hash, id, 3, Speed) // Saving Speed on the Dummy
    call SaveReal(Hash, id, 4, AoE) // The AoE of the Net
    
    call GroupAddUnit(Nets, Dummy) // Adding the Net to the Nets group
    call EnableTrigger(gg_trg_Nets_Loop) // Enabling the Loop
        
    call RemoveLocation(Point) // Removing Leaks
    set u = null // Removing Leaks
    set Dummy = null // Removing Leaks
endfunction

//===========================================================================
function InitTrig_Nets_Cast takes nothing returns nothing
    set gg_trg_Nets_Cast = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Nets_Cast, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Nets_Cast, Condition( function Trig_Nest_Cast_Conditions ) )
    call TriggerAddAction( gg_trg_Nets_Cast, function Trig_Nest_Cast_Actions )
endfunction

This one is the loop
JASS:
function Trig_Nest_Loop_Group_Actions takes nothing returns nothing
    local unit Net = GetEnumUnit() // The Picked Unit
    local integer id = GetHandleId(Net) // The Handle of the Net
    local real Speed = LoadReal(Hash, id, 3) // Speed
    local real Distance = LoadReal(Hash, id, 2)-Speed // Distance minus Speed
    local real Pointx // Used later if Distance to travel is still greater than 0
    local real Pointy // Used later if Distance to travel is still greater than 0
    local real Angle // Used later if Distance to travel is still greater than 0
    local unit looper // Used later if Distance to travel is still greater than 0
    local unit Dummy // Used later if Distance to travel is still greater than 0
    local real NewX // Used later if Distance to travel is still greater than 0
    local real NewY // Used later if Distance to travel is still greater than 0
    local real Netx // Used later if Distance to travel is still greater than 0
    local real Nety // Used later if Distance to travel is still greater than 0
    local real AoE // Used later if Distance to travel is still greater than 0
    local player p // Used later if Distance to travel is still greater than 0
    
    if Distance <= 0 then // If Distance is 0 or less
        call FlushChildHashtable(Hash, id) // Clear Hashtable
        call KillUnit(Net) // Kill the net
        call GroupRemoveUnit(Nets, Net) // Remove the Net From the Group
    else
        set AoE = LoadReal(Hash, id, 4) // The AoE of the Net
        set p = GetOwningPlayer(Net) 
        set Netx = GetUnitX(Net) // The Net X
        set Nety = GetUnitY(Net) // The Net Y
        set Pointx = LoadReal(Hash, id, 0) // Target X
        set Pointy = LoadReal(Hash, id, 1) // Target Y
        set Angle = Atan2(Pointy - Nety, Pointx - Netx) // The Angle between Net and Target Point
        call SetUnitX(Net, Netx + Speed * Cos(Angle)) // Move Net towards Target on X axis
        call SetUnitY(Net, Nety + Speed * Sin(Angle)) // Move Net towards Target on Y axis
        call SaveReal(Hash, id, 2, Distance) // Save the new distance left to travel
        call GroupEnumUnitsInRange(bj_lastCreatedGroup, Netx, Nety, AoE, null) // Pick Every Unit around the net
        loop
            set looper = FirstOfGroup(bj_lastCreatedGroup) // Picked Unit around the net
            exitwhen looper == null // Loop ends when there's no valid target
            if GetWidgetLife(looper) > 0 and IsUnitEnemy(looper, p) and GetUnitAbilityLevel(looper, 'Bena') > 0 then // If Target is alive and Is an Enemy and the Unit isn't already ensnared. Replace 'Bena' with the ID of your Ensnare buff
                set Dummy = CreateUnit(p, 'XXXX', GetUnitX(looper), GetUnitY(looper), 0) // Create the Dummy. Replace 'XXXX' with the Raw ID of your Dummy Caster
                call UnitApplyTimedLife(Dummy, 'BTLF', 0.5) // Apply 0.5 expiration timer
                call IssueTargetOrder(Dummy, "ensnare", looper) // Order it to ensnare the target
            endif
            call GroupRemoveUnit(bj_lastCreatedGroup, looper) // Remove the target unit from the group
        endloop
    endif
    
    set Net = null
    set looper = null
    set Dummy = null
endfunction

function Trig_Nest_Loop_Actions takes nothing returns nothing
    set bj_groupCountUnits = 0
    call ForGroup(Nets, function CountUnitsInGroupEnum)
    if bj_groupCountUnits > 0 then
        call ForGroup( Nets, function Trig_Nest_Loop_Group_Actions )
    else
        call DisableTrigger(gg_trg_Nets_Loop)
    endif
endfunction

//===========================================================================
function InitTrig_Nets_Loop takes nothing returns nothing
    set gg_trg_Nets_Loop = CreateTrigger(  )
    call TriggerRegisterTimerEvent( gg_trg_Nets_Loop, 0.03, true )
    call TriggerAddAction( gg_trg_Nets_Loop, function Trig_Nest_Loop_Actions )
endfunction
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
If you copy paste the scripts, and replace the Raw id's of the dummies and ability, it will work. You can see that you can configure the AoE, speed, distance, etc.
 
Level 3
Joined
Feb 9, 2008
Messages
63
If you copy paste the scripts, and replace the Raw id's of the dummies and ability, it will work. You can see that you can configure the AoE, speed, distance, etc.

i did what you said but it keeps getting errors like "undeclared variable"
what do i do?

Anyways heres the my 2nd attemp in improving my trigger please check again

  • Net Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Binding Net
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • NetIndex Equal to 0
        • Then - Actions
          • Trigger - Turn on Net Loop <gen>
        • Else - Actions
      • Set NetIndex = (NetIndex + 1)
      • Set NetTracker[NetIndex] = True
      • Set NetCaster[NetIndex] = (Triggering unit)
      • Set NetCasterPoint[NetIndex] = (Position of NetCaster[NetIndex])
      • Set NetDummyPoint[NetIndex] = (Target point of ability being cast)
      • Set NetDummy[NetIndex] = Net Dummy
      • Set NetCounter[NetIndex] = 0
      • Unit - Create 1 NetDummy[NetIndex] for (Owner of NetCaster[NetIndex]) at NetCasterPoint[NetIndex] facing NetCasterPoint[NetIndex]
      • Set Net[NetIndex] = (Last created unit)
      • Set NetDistance[NetIndex] = 0.00
      • Set NetSpeed[NetIndex] = 30.00
  • Net Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer NetInteger) from 1 to NetIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • NetTracker[NetInteger] Equal to True
            • Then - Actions
              • Set NetEndPoint[NetInteger] = (Distance between NetCasterPoint[NetInteger] and NetDummyPoint[NetInteger])
              • Set NetAngle[NetInteger] = (Angle from NetCasterPoint[NetInteger] to NetDummyPoint[NetInteger])
              • Set NetDistance[NetInteger] = (NetDistance[NetInteger] + NetSpeed[NetInteger])
              • Set NetPoint[NetInteger] = (NetCasterPoint[NetInteger] offset by NetDistance[NetInteger] towards NetAngle[NetInteger] degrees)
              • Unit - Move Net[NetInteger] instantly to NetPoint[NetInteger]
              • Custom script: call RemoveLocation(udg_NetPoint[udg_NetInteger])
              • Set NetArea[NetInteger] = (Units within 200.00 of (Position of Net[NetInteger]) matching ((((Matching unit) is A structure) Equal to False) and ((((Matching unit) is alive) Equal to True) and ((((Matching unit) is hidden) Equal to False) and ((((Matching unit) belongs to an enemy of (
              • Unit Group - Pick every unit in NetArea[NetInteger] and do (Actions)
                • Loop - Actions
                  • Set NetDummy[NetInteger] = Net Dummy 2
                  • Unit - Create 1 NetDummy[NetInteger] for (Owner of NetCaster[NetInteger]) at (Position of (Picked unit)) facing (Position of (Picked unit))
                  • Set NetDummy2[NetInteger] = (Last created unit)
                  • Unit - Add Bind Net Dummy to NetDummy2[NetInteger]
                  • Unit - Set level of Bind Net Dummy for NetDummy2[NetInteger] to (Level of Binding Net for NetCaster[NetInteger])
                  • Unit - Order NetDummy2[NetInteger] to Orc Raider - Ensnare (Picked unit)
                  • Unit - Add a 1.00 second Generic expiration timer to NetDummy2[NetInteger]
                  • Custom script: call DestroyGroup(udg_NetArea[udg_NetInteger])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • NetDistance[NetInteger] Greater than or equal to NetEndPoint[NetInteger]
                • Then - Actions
                  • Set NetTracker[NetInteger] = False
                  • Set NetIndex = (NetIndex - 1)
                  • Unit - Remove NetDummy2[NetInteger] from the game
                  • Unit - Remove Net[NetInteger] from the game
                  • Custom script: call RemoveLocation(udg_NetCasterPoint[udg_NetInteger])
                  • Custom script: call RemoveLocation(udg_NetDummyPoint[udg_NetInteger])
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • NetIndex Equal to 0
                    • Then - Actions
                      • Set NetIndex = 0
                      • Trigger - Turn off (This trigger)
                    • Else - Actions
                • Else - Actions
            • Else - Actions
The only leak (i think) this has is this
  • Set NetEndPoint[NetInteger] = (Distance between NetCasterPoint[NetInteger] and NetDummyPoint[NetInteger])
i dunno how to remove it or do i even need to remove it?
cause i dunno where to put the "call remove" function for it
it keeps getting errors whenever i try
 
Last edited:
Level 20
Joined
Jul 14, 2011
Messages
3,213
Oh, you need updated JNPG in order to use some of the features i used.

You don't need to remove the NetEndPoint because it's not a Point, it's a Real, and Reals doesn't leak. What you have to remove are the 2 points you're using for the Real, NetCasterPoint and NetDummyPoint.

You're still removing the Points ONLY when this is true
  • NetDistance[NetInteger] Greater than or equal to NetEndPoint[NetInteger]
So, yes, you're leaking a lot. You have to remove the locations in the same block you're declaring/using them (in this case) wich is the loop, not the -Then- actions block.

You're also checking If the NetIndex is Equal to 0 ONLY inside the "Then" actions, and you're doing it for every unit inside the Loop. You can check that outside the loop at the end of the trigger.

Try this: Create a copy of your 2 triggers, and convert them to custom text. See all the S#!t you have there, and compare it with the script i gave you :)

Sorry, once I found that JASS was so fast, awesome and easy; i stopped working with GUI so it's a bit confusing for me to understand the relation between all your variables :p
 
Status
Not open for further replies.
Top