- Joined
- Mar 3, 2006
- Messages
- 1,564
I don't know if anyone (vJASSers) remember about a problem I have in a spell that I posted in an old thread; that problem was about a shift in points between the target location and the actual location that the dummy unit stops at.
I tried to make a separate trigger to test location functions and X,Y coordinate functions, the trigger looked like this:
This worked fine and the unit goes exactly at the target w/o any shift. So whats wrong with my old script:
I tried to make a separate trigger to test location functions and X,Y coordinate functions, the trigger looked like this:
JASS:
globals
constant real T_INT = 0.01
constant real DISP = 5.00
unit u
location l
real xl
real yl
real Angle
timer tm = CreateTimer()
endglobals
function Move takes nothing returns nothing
local real X = GetUnitX(u)
local real Y = GetUnitY(u)
set X = X + DISP*Cos(Angle)
set Y = Y + DISP*Sin(Angle)
call SetUnitPosition(u,X,Y)
if DistanceBetweenPoints(GetUnitLoc(u),l) <= 2.5 then
call PauseTimer(tm)
call RemoveLocation(l)
endif
endfunction
function Create takes nothing returns nothing
set u = CreateUnit(Player(0),'ewsp',0,0,0)
set l = GetSpellTargetLoc()
set xl = GetLocationX(l)
set yl = GetLocationY(l)
//call CreateItem('btst',xl,yl)
set Angle = Atan2(yl - GetUnitY(u), xl - GetUnitX(u))
call TimerStart(tm,T_INT,true,function Move)
endfunction
//===========================================================================
function InitTrig_XY_move takes nothing returns nothing
set gg_trg_XY_move = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ(gg_trg_XY_move,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction( gg_trg_XY_move, function Create )
endfunction
This worked fine and the unit goes exactly at the target w/o any shift. So whats wrong with my old script:
JASS:
scope FireNova initializer Init
private keyword NovaData
private keyword MislData
globals
// Constants
private constant integer ABIL_ID = 'A000' // rawcode of the Dummy Spell
private constant integer M_UNIT_ID = 'e000' // rawcode of the Missile Unit
private constant integer N_UNIT_ID = 'e001' // rawcode of the Nova Unit
private constant integer NOVA_SIZE = 36 // number of the Nova Units
private constant real M_TIMER_INTERVAL = 0.03
private constant real N_TIMER_INTERVAL = 0.015
private constant real M_DIST = 32
private constant real N_DIST = 16.00
private constant real NOVA_RADIUS = 544.00 // radius of the Nova
private constant real dA = 360/NOVA_SIZE
private constant real AB_CONST_FACTOR = 50.00
private constant real AB_LEVEL_FACTOR = 50.00
private constant real AB_PREV_LVL_FACTOR = 1
private constant attacktype ATKTYPE = ATTACK_TYPE_MAGIC
private constant damagetype DMGTYPE = DAMAGE_TYPE_FIRE
// Variables
private timer mtm = CreateTimer()
private timer ntm = CreateTimer()
private MislData array temp_mdat
private NovaData array temp_ndat
private integer mindex = 0
private integer nindex = 0
private NovaData iFilter // Filter Data
private boolexpr fFilter // Filter function
private group TempGroup = CreateGroup()
endglobals
function NovaDamage takes integer al returns real
local real prevDmg
if al == 1 then
set prevDmg = 0
else
set prevDmg = NovaDamage.evaluate(al -1)
endif
return AB_CONST_FACTOR + AB_LEVEL_FACTOR * al + AB_PREV_LVL_FACTOR * prevDmg
endfunction
private struct NovaData
unit Caster
unit array Nova[NOVA_SIZE]
real expand
real Cx
real Cy
player Owner
group dGroup = CreateGroup() // Damaged Units Group
real dmg
static method NovaExpand takes nothing returns nothing
local thistype dat
local integer i = 0
local integer j
local real x
local real y
local real a
local unit u
loop // this loop cycles through all the casters which have cast the spell
exitwhen i >= nindex
set dat = temp_ndat[i]
// Nova Expanding
set j = 0
set a = 0
set dat.expand = dat.expand + N_DIST
loop
exitwhen j >= NOVA_SIZE
set x = dat.Cx + dat.expand * Cos( a * bj_DEGTORAD )
set y = dat.Cy + dat.expand * Sin( a * bj_DEGTORAD )
call SetUnitX( dat.Nova[j] , x )
call SetUnitY( dat.Nova[j] , y )
set j = j + 1
set a = a + dA
endloop
// Damage Units that the nova has reached
set iFilter = dat
call GroupEnumUnitsInRange(TempGroup, dat.Cx, dat.Cy, dat.expand, fFilter)
loop
set u = FirstOfGroup(TempGroup)
exitwhen u == null
call GroupAddUnit(dat.dGroup, u)
call UnitDamageTarget(dat.Caster, u, dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
call GroupRemoveUnit(TempGroup, u)
endloop
if dat.expand >= NOVA_RADIUS then // check if the nova has reached its max AoE
set nindex = nindex - 1
set temp_ndat[i] = temp_ndat[nindex]
set i = i - 1
call dat.destroy()
endif
set i = i + 1
endloop
set u = null
endmethod
static method create takes unit caster , real damage , real posX, real posY returns NovaData
local thistype dat = thistype.allocate()
local integer i = 0
local real A = 0.00
set dat.Caster = caster
set dat.Owner = GetOwningPlayer(dat.Caster)
set dat.Cx = posX
set dat.Cy = posY
set dat.dmg = damage
call DisplayTimedTextToPlayer(dat.Owner,0,0,10,"|cffff0000" + R2S(dat.dmg) + "|r")
loop
exitwhen i >= NOVA_SIZE
set dat.Nova[i] = CreateUnit( dat.Owner , N_UNIT_ID , dat.Cx , dat.Cy , A )
set A = A + dA
set i = i + 1
endloop
if nindex == 0 then
call TimerStart(ntm,N_TIMER_INTERVAL,true,function NovaData.NovaExpand)
endif
set temp_ndat[nindex] = dat
set nindex = nindex + 1
return dat
endmethod
static method FilterUnit takes nothing returns boolean
return GetWidgetLife(GetFilterUnit()) >= .305 and IsUnitEnemy(GetFilterUnit(),iFilter.Owner) and not IsUnitType(GetFilterUnit(),UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitInGroup(GetFilterUnit(),iFilter.dGroup)
endmethod
method onDestroy takes nothing returns nothing
local integer i = 0
loop
exitwhen i >= NOVA_SIZE
call KillUnit(.Nova[i])
set .Nova[i] = null
set .expand = 0
set i = i + 1
endloop
if nindex == 0 then
call PauseTimer(ntm)
endif
endmethod
endstruct
private struct MislData
unit Caster
unit Missile
location CastPoint
real Distance
real Damage
real face
static method MoveMissile takes nothing returns nothing
local MislData dat
local integer i = 0
local real X = 0
local real Y = 0
loop
exitwhen i >= mindex
set dat = temp_mdat[i]
set dat.Distance = dat.Distance - M_DIST
set X = GetUnitX(dat.Missile) + M_DIST * Cos(dat.face * bj_DEGTORAD)
set Y = GetUnitY(dat.Missile) + M_DIST * Sin(dat.face * bj_DEGTORAD)
if dat.Distance < M_DIST * 0.75 then
set mindex = mindex - 1
set temp_mdat[i] = temp_mdat[mindex]
set i = i - 1
call NovaData.create(dat.Caster , dat.Damage , GetUnitX(dat.Missile) , GetUnitY(dat.Missile))
call dat.destroy()
else
call SetUnitPosition(dat.Missile,X,Y)
endif
set i = i + 1
endloop
endmethod
static method create takes unit u , location target returns MislData
local MislData dat = MislData.allocate()
set temp_mdat[mindex] = dat
set dat.Caster = u
set dat.CastPoint = target
set dat.Distance = 0
set dat.Distance = DistanceBetweenPoints(GetUnitLoc(dat.Caster),dat.CastPoint)
set dat.face = AngleBetweenPoints(GetUnitLoc(dat.Caster) , dat.CastPoint)
set dat.Missile = CreateUnit(GetOwningPlayer(dat.Caster),M_UNIT_ID,GetUnitX(dat.Caster),GetUnitY(dat.Caster),dat.face)
set dat.Damage = NovaDamage(GetUnitAbilityLevel(u , ABIL_ID))
if mindex == 0 then
call TimerStart(mtm,M_TIMER_INTERVAL,true,function MislData.MoveMissile)
endif
set mindex = mindex + 1
return dat
endmethod
method onDestroy takes nothing returns nothing
call KillUnit(.Missile)
set .Missile = null
set .face = 0
call RemoveLocation(.CastPoint)
if mindex == 0 then
call PauseTimer(mtm)
endif
endmethod
endstruct
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == ABIL_ID
endfunction
private function Actions takes nothing returns nothing
call MislData.create(GetTriggerUnit(), GetSpellTargetLoc())
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function Conditions))
call TriggerAddAction(t,function Actions)
set fFilter = Filter(function NovaData.FilterUnit)
endfunction
endscope
infoFor more information about the old thread Click Here
RewardReputation for anyone who will help me