- Joined
- Aug 3, 2008
- Messages
- 2,345
I have been working on a projectile system which will launch a projectile from the specified point and it will travel a certain distance ('dist' argument) travelling at a certain speed ('speed' argument, not yet functioning correctly, but should be easy to fix, not my aim for this post). The projectile will, whenever it comes within a certain radius ('radius' argument) of an enemy, damage it. Now, I have including 2 boolean arguments: 'StopOnHit' which should cause the missile to stop once it hits something, but doesn't work properly, and if flagged true, just destroys the projectile almost as soon as I create it. The other boolean, 'DamageOwnUnits' also doesn't work. Any unit seems to be damaged by the missile. I believe this is caused by bad 'if' statements in the bold section of code (or at least the section wrapped in bold tags, which don't seem to function within JASS tags). Following is my code:
Yes, I did take ideas from Silvenon's knockback code, as you may have noticed
I hope someone can help me!
Thanks
JASS:
library ProjectileSystem initializer Init
globals
private timer Tim = CreateTimer()
private integer Total = 0
private boolexpr Cond = null
private integer array Ar
private real MAX_X
private real MAX_Y
private real MIN_X
private real MIN_Y
endglobals
private constant function Interval takes nothing returns real
return 0.04
endfunction
private constant function ProjectilePlayer takes nothing returns integer
return 13
endfunction
public struct Data
unit u
unit au
group hit
real d1
real d2
real d3
real sin
real cos
real dmg
real r
boolean soh
boolean ds
static method create takes unit au, integer dummyUnit, real x, real y, real rad, integer q, real d, real a, real dmg, boolean soh, boolean ds returns Data
local Data dat = Data.allocate()
set dat.au = au
set dat.u = CreateUnit(Player(ProjectilePlayer()), dummyUnit, x, y, a * bj_RADTODEG)
set dat.hit = CreateGroup()
set dat.d1 = 2 * d / (q + 1)
set dat.d2 = dat.d1
set dat.d3 = dat.d1 / q
set dat.sin = Sin(a)
set dat.cos = Cos(a)
set dat.dmg = dmg
set dat.r = rad
set dat.soh = soh
set dat.ds = ds
call UnitAddAbility(dat.u, 'Aloc')
if Total == 0 then
call TimerStart(Tim, Interval(), true, function Data.Execute)
endif
set Total = Total + 1
set Ar[Total - 1] = dat
return dat
endmethod
static method Execute takes nothing returns nothing
local Data dat
local integer i = 0
local real x
local real y
local group g = null
local unit u = null
local boolean Bool = false
loop
exitwhen i >= Total
set dat = Ar[i]
set dat.d2 = dat.d2 - dat.d3
set x = GetUnitX(dat.u) + dat.d1 * dat.cos
set y = GetUnitY(dat.u) + dat.d1 * dat.sin
[B]set g = CreateGroup()
call GroupEnumUnitsInRange(g, x, y, dat.r, null)
set u = FirstOfGroup(g)
debug call BJDebugMsg("checking conditions")
if (not dat.ds) then
if (not (GetOwningPlayer(u) == GetOwningPlayer(dat.au))) then
debug call BJDebugMsg("Conditions passed, proceeding to test if unit has already been hit")
if (not IsUnitInGroup(u, dat.hit) and u != null) then
debug call BJDebugMsg("Unit has not already been hit, proceeding to damage unit")
call UnitDamageTarget(dat.au, u, dat.dmg, true, true, ATTACK_TYPE_PIERCE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_METAL_LIGHT_SLICE)
call GroupAddUnit(dat.hit, u)
if (dat.soh) then
debug call BJDebugMsg("Unit has been hit, destroying projectile")
set Bool = true
endif
endif
endif
else
debug call BJDebugMsg("Conditions passed, proceeding to test if unit has already been hit")
if (not IsUnitInGroup(u, dat.hit) and u != null) then
debug call BJDebugMsg("Unit has not already been hit, proceeding to damage unit")
call UnitDamageTarget(dat.au, u, dat.dmg, true, true, ATTACK_TYPE_PIERCE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_METAL_LIGHT_SLICE)
call GroupAddUnit(dat.hit, u)
if (dat.soh) then
debug call BJDebugMsg("Unit has been hit, destroying projectile")
set Bool = true
endif
endif
endif
call DestroyGroup(g)
set g = null
set u = null[/B]
if (x < MAX_X and y < MAX_Y and x > MIN_X and y > MIN_Y) and not Bool then
call SetUnitX(dat.u, x)
call SetUnitY(dat.u, y)
endif
if dat.d2 <= 0 or (x > MAX_X or y > MAX_Y or x < MIN_X or y < MIN_Y) or Bool then
set Ar[i] = Ar[Total - 1]
set Total = Total - 1
call dat.destroy()
endif
set Bool = false
set i = i + 1
endloop
if Total == 0 then
call PauseTimer(Tim)
endif
endmethod
method onDestroy takes nothing returns nothing
call KillUnit(.u)
set .u = null
call DestroyGroup(.hit)
set .hit = null
endmethod
endstruct
function LaunchProjectile takes unit attacker, integer dummyUnit, real startx, real starty, real radius, real dist, real angle, real speed, real damage, boolean stopOnHit, boolean DamageOwnUnits returns nothing
call Data.create(attacker, dummyUnit, startx, starty, radius, R2I(speed / 1000 / Interval()), dist, bj_DEGTORAD * angle, damage, stopOnHit, DamageOwnUnits)
endfunction
private function Init takes nothing returns nothing
set MAX_X = GetRectMaxX(bj_mapInitialPlayableArea) - 64
set MAX_Y = GetRectMaxY(bj_mapInitialPlayableArea) - 64
set MIN_X = GetRectMinX(bj_mapInitialPlayableArea) + 64
set MIN_Y = GetRectMinY(bj_mapInitialPlayableArea) + 64
endfunction
endlibrary
Thanks
Last edited: