I want to link 2 units together. Imagine it like a rope between the 2 of them.
None of them can move further than XXX units away from the other, but it can stay closer to it than that.
An important condition is: none of the units should be able to pull the other one!
It would've been quite simple without this condition - I can just do periodic checks if the other unit is too far, and if it is - move it in range. However this way - the "dominant unit" could pull the other one.
At the moment I'm trying to do something else - every 0.03125 seconds I check if any of the units have changed its location: if only 1 of them has moved - I treat the other one as "dominant", if none of them has moved - do nothing, and if both of them have moved - check the distance between them, and if they are too far from eachother - move both of them with half of the "overdistance".
Can anyone think of a better way to do it?
EDIT: Here is the prototype code:
I will likely make it more readable later. I kind a did this just to test my concept.
The main problem with this code is that when 1 of the units is faster than the other, and both of them are moving in oposite directions - the faster 1 is slightly pulling the slower one. Apart from that, it actually works rather well.
None of them can move further than XXX units away from the other, but it can stay closer to it than that.
An important condition is: none of the units should be able to pull the other one!
It would've been quite simple without this condition - I can just do periodic checks if the other unit is too far, and if it is - move it in range. However this way - the "dominant unit" could pull the other one.
At the moment I'm trying to do something else - every 0.03125 seconds I check if any of the units have changed its location: if only 1 of them has moved - I treat the other one as "dominant", if none of them has moved - do nothing, and if both of them have moved - check the distance between them, and if they are too far from eachother - move both of them with half of the "overdistance".
Can anyone think of a better way to do it?
EDIT: Here is the prototype code:
JASS:
function Bond takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer id = GetHandleId(t)
local unit u1 = LoadUnitHandle(udg_Table, id, 'unt1')
local unit u2 = LoadUnitHandle(udg_Table, id, 'unt2')
local real x11 = LoadReal(udg_Table, id, 'ut1x')
local real y11 = LoadReal(udg_Table, id, 'ut1y')
local real x21 = LoadReal(udg_Table, id, 'ut2x')
local real y21 = LoadReal(udg_Table, id, 'ut2y')
local real x12 = GetUnitX(u1)
local real y12 = GetUnitY(u1)
local real x22 = GetUnitX(u2)
local real y22 = GetUnitY(u2)
local boolean b1 = x11 - x12 < 1 and x11 - x12 > -1 and y11 - y12 < 1 and y11 - y12 > -1
local boolean b2 = x21 - x22 < 1 and x21 - x22 > -1 and y21 - y22 < 1 and y21 - y22 > -1
local real a
local real x
local real y
if not (b1 and b2) and (x22-x12)*(x22-x12) + (y22-y12)*(y22-y12) > 90000 then
if b1 and not b2 then
set a = Atan2(y22 - y12, x22 - x12)
set x22 = x11 + 300*Cos(a)
set y22 = y11 + 300*Sin(a)
call SetUnitX(u2, x22)
call SetUnitY(u2, y22)
elseif b2 and not b1 then
set a = Atan2(y12 - y22, x12 - x22)
set x12 = x21 + 300*Cos(a)
set y12 = y21 + 300*Sin(a)
call SetUnitX(u1, x12)
call SetUnitY(u1, y12)
else
set x = (x12 + x22)/2
set y = (y12 + y22)/2
set a = Atan2(y22 - y, x22 - x)
set x22 = x + 150*Cos(a)
set y22 = y + 150*Sin(a)
call SetUnitX(u2, x22)
call SetUnitY(u2, y22)
set a = Atan2(y12 - y, x12 - x)
set x12 = x + 150*Cos(a)
set y12 = y + 150*Sin(a)
call SetUnitX(u1, x12)
call SetUnitY(u1, y12)
endif
endif
call SaveReal(udg_Table, id, 'ut1x', x12)
call SaveReal(udg_Table, id, 'ut1y', y12)
call SaveReal(udg_Table, id, 'ut2x', x22)
call SaveReal(udg_Table, id, 'ut2y', y22)
call TimerStart(t, 0.03125, false, function Bond)
set u1 = null
set u2 = null
set t = null
endfunction
function Trig_Magic_Bond_Conditions takes nothing returns boolean
local timer t
local unit u1
local unit u2
local integer id
if GetSpellAbilityId() == 'A08O' then
set t = GetFreeTimer()
set u1 = GetTriggerUnit()
set u2 = GetSpellTargetUnit()
set id = GetHandleId(t)
call SaveUnitHandle(udg_Table, id, 'unt1', u1)
call SaveUnitHandle(udg_Table, id, 'unt2', u2)
call SaveReal(udg_Table, id, 'ut1x', GetUnitX(u1))
call SaveReal(udg_Table, id, 'ut1y', GetUnitY(u1))
call SaveReal(udg_Table, id, 'ut2x', GetUnitX(u2))
call SaveReal(udg_Table, id, 'ut2y', GetUnitY(u2))
call TimerStart(t, 0.03125, false, function Bond)
set u1 = null
set u2 = null
set t = null
endif
return false
endfunction
//===========================================================================
function InitTrig_Magic_Bond takes nothing returns nothing
set gg_trg_Magic_Bond = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Magic_Bond, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Magic_Bond, Condition( function Trig_Magic_Bond_Conditions ) )
endfunction
The main problem with this code is that when 1 of the units is faster than the other, and both of them are moving in oposite directions - the faster 1 is slightly pulling the slower one. Apart from that, it actually works rather well.
Last edited: