Sei sulla pagina 1di 6

User

library Missile initializer Init


//CONSTANTS - change these suitably.
globals
public constant real FPS = 60.00
private constant integer DUMMY_ID = 'MSdm'
private constant player OWNER = Player(15)
endglobals
//END CONSTANTS
//MAIN SYSTEM CODE - do NOT alter unless you know what you're doing.
globals
private Missile array Dat
private integer Index = 0
private timer Tim = CreateTimer()
private boolexpr Conds
private group Missiles = CreateGroup()
Missile GetEventMissile
endglobals
struct MissileActions
stub method onHit takes nothing returns boolean
return false
endmethod
stub method onLoop takes nothing returns boolean
return true
endmethod
endstruct
//kinda transfers all the units in a group into a different group.
private function AddGroup takes group a, group b returns nothing
local unit u
loop
set u = FirstOfGroup(b)
exitwhen u == null
call GroupAddUnit(a, u)
call GroupRemoveUnit(b, u)
endloop
endfunction
private function CondsFunc takes nothing returns boolean
return (not IsUnitInGroup(GetFilterUnit(), GetEventMissile.hg)) and GetE
ventMissile.Caster != GetFilterUnit() and GetUnitTypeId(GetFilterUnit()) != DUMM
Y_ID and GetWidgetLife(GetFilterUnit()) > 0.405
endfunction
private function Execute takes nothing returns nothing
local integer i = 0
local
local
local
local

real
real
real
real

angle
dx
dy
dist

loop
exitwhen i >= Index
set GetEventMissile = Dat[i]
//calculate how far the missile the missile has travelled
set GetEventMissile.CurrentDist = GetEventMissile.CurrentDist + GetE
ventMissile.sp
//If the missile is homing onto a target, recalculate a few values
if GetEventMissile.Homing then
//get the new target x/y
set GetEventMissile.TargetX = GetUnitX(GetEventMissile.Target)
set GetEventMissile.TargetY = GetUnitY(GetEventMissile.Target)
//get the angle between the missile and the target
set angle = Atan2(GetEventMissile.TargetY - GetEventMissile.Y, G
etEventMissile.TargetX - GetEventMissile.X)
//calculate the sin/cos of the angle
set GetEventMissile.sn = Sin(angle)
set GetEventMissile.cs = Cos(angle)
//make the missile face towards the target
call SetUnitFacing(GetEventMissile.Dummy, angle * bj_RADTODEG)
//cacluclate the distance between the missile and its target
set dx = GetEventMissile.TargetX - GetEventMissile.X
set dy = GetEventMissile.TargetY - GetEventMissile.Y
set dist = SquareRoot(dx * dx + dy * dy)
else
set dist = GetEventMissile.StartDist - GetEventMissile.CurrentDi
st
endif
//calculate the new x/y coordinates
set GetEventMissile.X = GetEventMissile.X + GetEventMissile.sp * Get
EventMissile.cs // set x = x + speed * cos
set GetEventMissile.Y = GetEventMissile.Y + GetEventMissile.sp * Get
EventMissile.sn // set y = y + speed * sin
//run the onLoop actions, destroying the missile if they return fals
e
if GetEventMissile.ma != 0 then
if not GetEventMissile.ma.onLoop() then
call GetEventMissile.destroy()
endif
endif
//if the missile is collideable, check for collision
if GetEventMissile.Radius > 0.00 then
//enumerate the units within range of the missile, which aren't
missiles
call GroupEnumUnitsInRange(GetEventMissile.hu, GetEventMissile.X
, GetEventMissile.Y, GetEventMissile.Radius, Conds)
//if the enumeration picked up any units, then...
if FirstOfGroup(GetEventMissile.hu) != null then
//run the onHit actions, and if they return false then...
if not GetEventMissile.ma.onHit() and GetEventMissile.ma !=

0 then
//destroy the missile
call GetEventMissile.destroy()
endif
//add the hit units to the hit units group so the system doe
sn't falsely
//think they're hit more than once
call AddGroup(GetEventMissile.hg, GetEventMissile.hu)
endif
endif
//calculate the absolute value of the distance remaining
if dist < 0 then
set dist = -dist
endif
//if the distance remaining is less than the speed of the missile th
en...
if dist < GetEventMissile.sp then
//tell the user the missile has reached its target and...
set GetEventMissile.TargetReached = true
set GetEventMissile.OnTarget = true
//run the onHit actions, destroying the missile if they return f
alse
if not GetEventMissile.ma.onHit() and GetEventMissile.ma != 0 th
en
call GetEventMissile.destroy()
endif
set GetEventMissile.OnTarget = false
endif
//and finally move the missile.
call SetUnitX(GetEventMissile.Dummy, GetEventMissile.X)
call SetUnitY(GetEventMissile.Dummy, GetEventMissile.Y)
set i = i + 1
endloop
endfunction
struct Missile
unit
string

Dummy = null
fs = ""

//the actual missile unit


//the model path of the miss

effect

SFX = null

//the actual model

unit
unit

Caster = null
Target = null

//missile caster or jumper


//homing target

boolean
boolean
real

dm = false
Homing = false
Radius = 0.

//dummy, or preplaced unit?


//homing?
//radius for collision

real
real
real
real
real
real

StartX = 0.
StartY = 0.
X = 0.
Y = 0.
TargetX = 0.
TargetY = 0.

//start x
//start y
//current x
//current y
//target x
//target y

real

sn = 0.

//sin

ile

real
real

cs = 0.
StartDist = 0

//cos
//starting distance from the

real

CurrentDist = 0

//distance from target

real

sp = 0.

//speed

group
group

hu = null
hg = null

//the units hit this loop


//units which have already b

boolean
boolean

TargetReached = false
OnTarget = false

//target reached?
//on target now?

MissileActions

ma = 0

//the onHit and onLoop actio

integer
integer

data = 0
id = 0

//attached data
//the array index of the mis

target

een hit

ns

sile
//internal create method
private static method coreCreate takes real radius, MissileActions ma re
turns Missile
local Missile d = Missile.allocate()
set
set
set
set

d.hg = CreateGroup()
d.hu = CreateGroup()
d.Radius = radius
d.ma = ma

return d
endmethod
//creates a new missile with the given model
static method create takes string sfx, real x, real y, real radius, Miss
ileActions actions returns Missile
local Missile d = Missile.coreCreate(radius, actions)
set
set
set
set
set
set

d.fs = sfx
d.StartX = x
d.StartY = y
d.X = x
d.Y = y
d.dm = true

return d
endmethod
//creates a missile from an existing unit
static method createFromUnit takes unit u, real radius, MissileActions a
ctions returns Missile
local Missile d = Missile.coreCreate(radius, actions)
set
set
set
set
set

d.Dummy = u
d.StartX = GetUnitX(u)
d.StartY = GetUnitY(u)
d.X = d.StartX
d.Y = d.StartY

return d
endmethod
method operator HitUnits takes nothing returns group
local group g = CreateGroup()
set bj_groupAddGroupDest = g
call ForGroup(.hu, function GroupAddGroupEnum)
return g
endmethod
method operator Speed takes nothing returns real
return .sp * FPS
endmethod
method operator Speed= takes real speed returns nothing
set .sp = speed / FPS
endmethod
//Internal function to fire the missile
private method fire takes unit caster, real speed returns nothing
local real angle = Atan2(.TargetY - .Y, .TargetX - .X)
local real dx = .TargetX - .X
local real dy = .TargetY - .Y
set .sn = Sin(angle)
set .cs = Cos(angle)
set .StartDist = SquareRoot(dx * dx + dy * dy)
if .Dummy == null then
set .Dummy = CreateUnit(OWNER, DUMMY_ID, .X, .Y, angle * bj_RADT
ODEG)
set .SFX = AddSpecialEffectTarget(.fs, .Dummy, "origin")
endif
set .Caster = caster
set .sp = speed / FPS
call GroupAddUnit(Missiles, .Dummy)
set Dat[Index] = this
set .id = Index
set Index = Index + 1
if Index == 1 then
call TimerStart(Tim, 1./FPS, true, function Execute)
endif
endmethod
//fires the missile at a point!
method fireFixed takes unit caster, real targetX, real targetY, real spe
ed returns nothing
set .Homing = false
set .TargetX = targetX
set .TargetY = targetY
call .fire(caster, speed)
endmethod
//fires the missile at a unit!

method fireTarget takes unit caster, unit target, real speed returns not
hing
set .Homing = true
set .Target = target
set .TargetX = GetUnitX(.Target)
set .TargetY = GetUnitY(.Target)
call .fire(caster, speed)
endmethod
method onDestroy takes nothing returns nothing
set Index = Index - 1
set Dat[.id] = Dat[Index]
set Dat[.id].id = .id
call .ma.destroy()
call GroupClear(.hg)
call DestroyGroup(.hg)
call DestroyGroup(.hu)
if .SFX != null then
call DestroyEffect(.SFX)
endif
call GroupRemoveUnit(Missiles, .Dummy)
if .dm then
call KillUnit(.Dummy)
endif
endmethod
endstruct
private function Init takes nothing returns nothing
set Conds = Filter(function CondsFunc)
endfunction
endlibrary

Potrebbero piacerti anche