Basically, i am in need of a way to make it so that the unit that is jumping is moved to the correct location, even if the target moves.
For example;
Its hard to explain it in pictures, but basically i need the unit to be able to follow the target, and still keep a good parabolic effect.
For those of you who have played DotA recently, Its basically like the new Toss, where the tossed unit will change directions according to the targets location.
This is what i have so far:
What i am currently doing is every interval, im setting the new maxdist to the distance between the start and the heroes current location, then setting the movedist accordingly. I also change the angle accordingly as well.
If you do have a way of doing this, but it uses the parabola function instead of how i do it, it is okay as well, as long as it works.
Its still very rough, and so far it bugs like crazy.
Note: I am using Z coordinates to make it look better over changing terrain, and to use the animations of vexorians dummy unit, so that arrows can be given a proper arc.
For example;
Code:
Normal:
*
* *
* *
* *
U T
When T moves:
*
* *
* *
* *
U * T
How i want it:
*
* *
* *
* *
U T
Its hard to explain it in pictures, but basically i need the unit to be able to follow the target, and still keep a good parabolic effect.
For those of you who have played DotA recently, Its basically like the new Toss, where the tossed unit will change directions according to the targets location.
This is what i have so far:
JASS:
scope SoulTransferral initializer Init
globals
private constant integer Abil_id = 039;A000039;
private constant integer Dummy_id = 039;u001039;
private constant integer Crow_form = 039;Amrf039;
private constant real Interval = 0.04
private constant real Airtime = 1.50
private constant string Incomplete_sfx = "Objects\\Spawnmodels\\Undead\\UndeadDissipate\\UndeadDissipate.mdl"
private constant string Soul_sfx = "Abilities\\Spells\\Other\\BlackArrow\\BlackArrowMissile.mdl" // "Abilities\\Weapons\\ZigguratMissile\\ZigguratMissile.mdl"
private constant string Point = "chest"
endglobals
//=======================================================================
private function Soul_transfer_interval takes integer lvl returns real
return 2.00 // 6.00 - (1.00 * lvl)
endfunction
private function Enemy_soul_chance takes integer lvl returns integer
return 100
endfunction
private function Radius takes integer lvl returns real
return 800.00
endfunction
private function BodyFilt takes nothing returns boolean
return GetWidgetLife(GetFilterUnit()) <= 0.405 and IsUnitType(GetFilterUnit(),UNIT_TYPE_MECHANICAL) == false
endfunction
//=======================================================================
private keyword Data
private keyword Jump
globals
private Data array D
private Jump array J
private integer DT = 0
private integer JT = 0
private timer Timer = null
private real Game_MaxX = 0.00
private real Game_MinX = 0.00
private real Game_MaxY = 0.00
private real Game_MinY = 0.00
private location Temploc = null
private boolexpr Truefilt = null
private boolexpr Bodyfilt = null
endglobals
//=======================================================================
private function DistanceXY takes real x1, real y1, real x2, real y2 returns real
return SquareRoot((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))
endfunction
private function AngleXY takes real x1, real y1, real x2, real y2 returns real
return Atan2((y2 - y1),(x2 - x1))
endfunction
private function MoveDist takes real Maxdist returns real
return Maxdist / (Airtime / Interval)
endfunction
private function ConvertCount takes integer i returns real
return (50.00 / (Airtime / Interval)) * i
endfunction
private function GetCoordZ takes real x, real y returns real
call MoveLocation (Temploc,x,y)
return GetLocationZ (Temploc)
endfunction
private function SetUnitZ takes unit u, real h returns boolean
local real z = h - GetCoordZ(GetUnitX(u),GetUnitY(u))
if z > 0.00 then
call SetUnitFlyHeight(u,z,0.00)
return false
else
return true
endif
endfunction
private function GetUnitZ takes unit u returns real
return GetCoordZ(GetUnitX(u),GetUnitY(u)) + GetUnitFlyHeight(u)
endfunction
private function SafeX takes real x returns real
if x<Game_MinX then
return Game_MinX
elseif x>Game_MaxX then
return Game_MaxX
endif
return x
endfunction
private function SafeY takes real y returns real
if y<Game_MinY then
return Game_MinY
elseif y>Game_MaxY then
return Game_MaxY
endif
return y
endfunction
//=======================================================================
private struct Data
unit cast = null
real time = 0.00
group g = CreateGroup()
endstruct
//=======================================================================
private struct Jump
unit cast = null
unit u = null
real castx = 0.00
real casty = 0.00
real ux = 0.00
real uy = 0.00
real cos = 0.00
real sin = 0.00
real maxdist = 0.00
real movedist = 0.00
integer i = 1
integer lvl = 0
effect sfx = null
static method create takes unit caster, unit body, integer level returns Jump
local Jump j = Jump.allocate()
local real x = GetUnitX(caster)
local real y = GetUnitY(caster)
local real tmpang = 0.00
set j.cast = caster
set j.u = CreateUnit(GetOwningPlayer(j.cast),Dummy_id,GetUnitX(body),GetUnitY(body),0.00)
set j.ux = GetUnitX(j.u)
set j.uy = GetUnitY(j.u)
set tmpang = AngleXY(j.ux,j.uy,x,y)
set j.cos = Cos(tmpang)
set j.sin = Sin(tmpang)
set j.maxdist = DistanceXY(x,y,j.ux,j.uy)
set j.movedist = MoveDist(j.maxdist)
set j.lvl = level
set j.sfx = AddSpecialEffectTarget(Soul_sfx,j.u,Point)
call UnitAddAbility(j.u,Crow_form)
call UnitRemoveAbility(j.u,Crow_form)
call SetUnitPathing(j.u,false)
set JT = JT + 1
set J[JT] = j
return j
endmethod
private method onDestroy takes nothing returns nothing
call DestroyEffect(.sfx)
set .sfx = null
set .u = null
set .cast = null
endmethod
endstruct
//=======================================================================
private function Update takes nothing returns nothing
local Jump j = 0
local integer lvl = 0
local integer i = 1
local integer anim = 0
local real tmpang = 0.00
local real tmpheight = 0.00
local real tmpdist = 0.00
local real height = 0.00
local real heightdiff = 0.00
local real count = 0.00
local real speed = 0.00
local real x = 0.00
local real y = 0.00
local real xx = 0.00
local real yy = 0.00
local unit u = null
loop
exitwhen i > DT
if GetWidgetLife(D<i>.cast) > 0.405 then
set x = GetUnitX(D<i>.cast)
set y = GetUnitY(D<i>.cast)
set lvl = GetUnitAbilityLevel(D<i>.cast,Abil_id)
if D<i>.time == Soul_transfer_interval(lvl) then
set D<i>.time = 0.00
call GroupEnumUnitsInRange(D<i>.g,x,y,Radius(lvl),Bodyfilt)
set u = FirstOfGroup(D<i>.g)
if u != null then
if IsUnitEnemy(u,GetOwningPlayer(D<i>.cast)) then
if GetRandomInt(0,100) <= Enemy_soul_chance(lvl) then
set j = Jump.create(D<i>.cast,u,lvl)
else
call DestroyEffect(AddSpecialEffect(Incomplete_sfx,GetUnitX(u),GetUnitY(u)))
endif
else
set j = Jump.create(D<i>.cast,u,lvl)
endif
endif
endif
set D<i>.time = D<i>.time + Interval
endif
set i = i + 1
endloop
set i = 1
loop
exitwhen i > JT
set x = GetUnitX(J<i>.u)
set y = GetUnitY(J<i>.u)
if J<i>.i < (Airtime / Interval) then
set count = ConvertCount(J<i>.i)
set height = (count - 25.00) * (count - 25.00)
set tmpheight = GetUnitZ(J<i>.u)
set heightdiff = height - tmpheight
set xx = GetUnitX(J<i>.cast)
set yy = GetUnitY(J<i>.cast)
set J<i>.maxdist = DistanceXY(xx,yy,j.ux,j.uy)
set J<i>.movedist = MoveDist(J<i>.maxdist)
set tmpang = AngleXY(x,y,xx,yy)
set J<i>.cos = Cos(tmpang)
set J<i>.sin = Sin(tmpang)
set speed = J<i>.i * J<i>.movedist
set xx = SafeX(J<i>.ux + speed * J<i>.cos)
set yy = SafeY(J<i>.uy + speed * J<i>.sin)
set tmpdist = DistanceXY(x,y,xx,yy)
set anim = R2I(Atan2(heightdiff,tmpdist) * bj_RADTODEG + 90.50)
if anim >= 180 then
set anim = 179
elseif anim < 0 then
set anim = 0
endif
call SetUnitPosition(J<i>.u,xx,yy)
call SetUnitZ(J<i>.u,(625.00 - height))
call SetUnitAnimationByIndex(J<i>.u,anim)
call SetUnitFacing(J<i>.u,tmpang * bj_RADTODEG)
set J<i>.i = J<i>.i + 1
else
call J<i>.destroy()
set J<i> = J[JT]
set JT = JT - 1
set i = i - 1
endif
set i = i + 1
endloop
set u = null
endfunction
//=======================================================================
private function Actions takes nothing returns nothing
local unit cast = GetTriggerUnit()
local Data d = 0
if GetLearnedSkill() == Abil_id and GetUnitAbilityLevel(cast,Abil_id) == 1 and IsUnitIllusion(cast) == false then
set d = Data.create()
set d.cast = cast
set DT = DT + 1
if DT == 1 and JT == 0 then
call TimerStart(Timer,Interval,true,function Update)
endif
set D[DT] = d
endif
set cast = null
endfunction
//=======================================================================
private function TrueFilt takes nothing returns boolean
return true
endfunction
//=======================================================================
private function Init takes nothing returns nothing
local trigger trig = CreateTrigger()
local integer i = 0
set Timer = CreateTimer()
set Temploc = Location(0.00,0.00)
set Truefilt = Filter(function TrueFilt)
set Bodyfilt = Filter(function BodyFilt)
set Game_MaxX = GetRectMaxX(bj_mapInitialPlayableArea) - 64.00
set Game_MinX = GetRectMinX(bj_mapInitialPlayableArea) + 64.00
set Game_MaxY = GetRectMaxY(bj_mapInitialPlayableArea) - 64.00
set Game_MinY = GetRectMinY(bj_mapInitialPlayableArea) + 64.00
loop
call TriggerRegisterPlayerUnitEvent(trig,Player(i),EVENT_PLAYER_HERO_SKILL,Truefilt)
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddAction(trig,function Actions)
endfunction
endscope
</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>
What i am currently doing is every interval, im setting the new maxdist to the distance between the start and the heroes current location, then setting the movedist accordingly. I also change the angle accordingly as well.
If you do have a way of doing this, but it uses the parabola function instead of how i do it, it is okay as well, as long as it works.
Its still very rough, and so far it bugs like crazy.
Note: I am using Z coordinates to make it look better over changing terrain, and to use the animations of vexorians dummy unit, so that arrows can be given a proper arc.