- Joined
- Jul 25, 2014
- Messages
- 490
JASS:
//Linked list recycling function
function BE_Recycle takes integer Node returns nothing
if (udg_BE_LastNode == Node) then
set udg_BE_LastNode = udg_BE_PrevNode[Node]
endif
set udg_BE_RecycleNodes[udg_BE_RecyclableNodes] = Node
set udg_BE_RecyclableNodes = udg_BE_RecyclableNodes + 1
set udg_BE_NextNode[udg_BE_PrevNode[Node]] = udg_BE_NextNode[Node]
set udg_BE_PrevNode[udg_BE_NextNode[Node]] = udg_BE_PrevNode[Node]
set udg_BE_AbilityCounter = udg_BE_AbilityCounter - 1
if (udg_BE_AbilityCounter == 0) then
call PauseTimer(udg_BE_Timer)
endif
endfunction
//Below is the main function of the spell (loop), it pulls one closest enemy towards the enchanted object
//If the unit goes out of range, selects a new target and exceeds the duration
function BE_Loop takes nothing returns nothing
local real x
local real y
local real z
local real x2
local real y2
local real z2
local real dx
local real dy
local integer Node = 0
local integer TempInt = 0
local real angle
local unit u
local real d
local real aoe = 300
loop
set Node = udg_BE_NextNode[Node]
exitwhen Node == 0
if udg_BE_Duration[Node] > 0.00 then
set udg_BE_Duration[Node] = udg_BE_Duration[Node] - 0.031250
set x = GetUnitX(udg_BE_EnchantedObj[Node])
set y = GetUnitY(udg_BE_EnchantedObj[Node])
// Calculating the nearest unit
if udg_BE_Check[Node] == 0 then
call GroupEnumUnitsInRange(udg_BE_TempGroup, x, y, aoe, null)
loop
set u = FirstOfGroup(udg_BE_TempGroup)
exitwhen u == null
set x2 = GetUnitX(u)
set y2 = GetUnitY(u)
set dx = x2 - x
set dy = y2 - y
set d = SquareRoot(dx*dx + dy*dy)
if d < aoe and u != udg_BE_EnchantedObj[Node] and GetUnitAbilityLevel(u, 'ACEV') == 0 and IsUnitAlly(u, udg_BE_Player[Node]) == false and not(IsUnitType(u, UNIT_TYPE_DEAD)) then
set udg_BE_Target[Node] = FirstOfGroup(udg_BE_TempGroup)
set aoe = d
endif
call GroupRemoveUnit(udg_BE_TempGroup, u)
endloop
endif
// Setting up the global integer to keep the spell from checking for a new target
if udg_BE_Check[Node] == 0 and udg_BE_Target[Node] != null then
set udg_BE_Check[Node] = 1
set udg_BE_Duration[Node] = 5.00
endif
// Pulling the enemy
if udg_BE_Target[Node] != null then
set z = GetUnitFlyHeight(udg_BE_EnchantedObj[Node]) + 50.00
set x2 = GetUnitX(udg_BE_Target[Node])
set y2 = GetUnitY(udg_BE_Target[Node])
set z2 = GetUnitFlyHeight(udg_BE_Target[Node]) + 50.00
call MoveLightningEx(udg_BE_Lightning[Node], false, x, y, z, x2, y2, z2)
set angle = Atan2(y - y2, x - x2)
if (GetUnitAbilityLevel(udg_BE_EnchantedObj[Node], 'A0AX') == 1) then
call SetUnitX(udg_BE_Target[Node], x2 + 9.375 * Cos(angle)) // 300 MS
call SetUnitY(udg_BE_Target[Node], y2 + 9.375 * Sin(angle)) // 300 MS
else
call SetUnitX(udg_BE_Target[Node], x2 + 6.25 * Cos(angle)) // 200 MS
call SetUnitY(udg_BE_Target[Node], y2 + 6.25 * Sin(angle)) // 200 MS
endif
set dx = x2 - x
set dy = y2 - y
set d = SquareRoot(dx*dx + dy*dy)
endif
// Checking if the distance has been exceeded
if d > 500 and udg_BE_Target[Node] != null and udg_BE_Check[Node] == 1 then
set udg_BE_Duration[Node] = 0.00
endif
// If the duration has ended, clean up
else
call DestroyLightning(udg_BE_Lightning[Node])
call DestroyEffect(udg_BE_SpecialEf[Node])
call BE_Recycle(Node)
endif
endloop
endfunction
// Linked list node creation
function BE_CreateNode takes nothing returns integer
local integer Node = 0
if (udg_BE_RecyclableNodes == 0) then
set udg_BE_NodeNumber = udg_BE_NodeNumber + 1
set Node = udg_BE_NodeNumber
else
set udg_BE_RecyclableNodes = udg_BE_RecyclableNodes - 1
set Node = udg_BE_RecycleNodes[udg_BE_RecyclableNodes]
endif
set udg_BE_NextNode[Node] = 0
set udg_BE_NextNode[udg_BE_LastNode] = Node
set udg_BE_PrevNode[Node] = udg_BE_LastNode
set udg_BE_LastNode = Node
set udg_BE_AbilityCounter = udg_BE_AbilityCounter + 1
if (udg_BE_AbilityCounter == 1) then
call TimerStart(udg_BE_Timer, 0.031250, true, function BE_Loop)
endif
return Node
endfunction
// Function onCast, sets up the base for the ability
function BE_OnCast takes nothing returns boolean
local integer Node
local unit u
local real x
local real y
local real z
local integer i
local integer i2
local integer count = 0
local integer random
// Checking if the casted ability is right
if (GetSpellAbilityId() == 'A0AV') then
set Node = BE_CreateNode()
set udg_BE_Player[Node] = GetTriggerPlayer()
set udg_BE_Target[Node] = null
set udg_BE_Check[Node] = 0
set udg_BE_Duration[Node] = 6.00
set x = GetSpellTargetX()
set y = GetSpellTargetY()
// Getting the random unit from the targeted AoE
call GroupEnumUnitsInRange(udg_BE_TempGroup, x, y, 300, null)
loop
set u = FirstOfGroup(udg_BE_TempGroup)
exitwhen u == null
set i = GetUnitAbilityLevel(u, 'A0AX')
set i2 = GetUnitAbilityLevel(u, 'ACEV')
if (not IsUnitType(u, UNIT_TYPE_DEAD)) and (not IsUnitType(u, UNIT_TYPE_STRUCTURE)) and (i2 == 0 or i == 1) then
set count = count + 1
call GroupAddUnit(udg_BE_Swap, u)
endif
call GroupRemoveUnit(udg_BE_TempGroup, u)
endloop
set random = GetRandomInt(0, count)
set count = 0
loop
set u = FirstOfGroup(udg_BE_Swap)
exitwhen u == null
set count = count + 1
if count == random then
set udg_BE_Unit = u
endif
call GroupRemoveUnit(udg_BE_Swap, u)
endloop
// Adding the lightning and the special "brilliance aura" effect to the target
set udg_BE_EnchantedObj[Node] = udg_BE_Unit
set udg_BE_SpecialEf[Node] = AddSpecialEffectTarget("Abilities\\Spells\\Human\\Brilliance\\Brilliance.mdl", udg_BE_EnchantedObj[Node], "origin")
set z = GetUnitFlyHeight(udg_BE_EnchantedObj[Node]) + 50.00
set udg_BE_Lightning[Node] = AddLightningEx("CHIM", false, x, y, z, x, y, z)
endif
return false
endfunction
// Initializing the trigger
function InitTrig_Binding_Enchant takes nothing returns nothing
local trigger BE = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(BE, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(BE, Condition(function BE_OnCast))
endfunction
The spell is called Binding Enchant and here is its tooltip:
The Shaman enchants one random unit in the targeted AoE. Should another unit come close to the enchanted object, it will get pulled and snagged and pulled towards it. Duration is reset once the target has been found. The leash can be broken if distance becomes greater than 500.
However its indexing/deindexing with the linked list is somehow incorrect. I deleted all the actions at one point, leaving only the linked list + timer structure and the loop only fired once.
I would appreciate it if someone would review this spell and tell me what am I doing wrong.
Already a huge thanks to KILLCIDE for improving the coding in this spell, however, we did not completely debunk what's wrong.
Last edited: