- Joined
- Mar 6, 2012
- Messages
- 64
So I am currently created a missile system which is supposed to help me create missiles for various purposes. The system runs specified trigger on "impact" making it usable for all kind of stuff. For example, the trigger makes the caster teleport on impact location, while having dmg at the same time or other crazy triggers you can think of. I'm pretty sure this system is not optimized and not in its best form yet and that is why I am posting it here for critiques and for improvement.
Credits to Anitarf for his Vector library.
Credits to Anitarf for his Vector library.
vJASS:
// Missile System by Blink
library MissileSystem2 requires Vector
globals
real lastMissileX
real lastMissileY
real lastMissileZ
real lastMissileAngleXY
real lastMissileAngleXZ
unit lastMissileTarget
unit lastMissileOwner
Missile lastMissileCreated
endglobals
struct Missile
//missile owner and target
private unit owner
private unit target
private group hitGroup
//effect attribute
private effect model
//missile position
private real x
private real y
private real z
//missile target position
private real tx
private real ty
private real tz
//rotation attributes
private vector direction
private real turnrate
//distance attributes
private real distance //distance left for missile to travel
private real velocity
//hit radius
private real hitrad
private real hitZoffset
//target filter
private boolexpr filter
//missile type
private boolean FUHit // first unit hit ,default is true
private boolean homing
private boolean passThrough
//other attributes ie. clipping,dropping
private boolean clipping
private boolean dropping
private boolean willDrop
//trigger that will execute when missile hits
private trigger HitTrig
//code stuff
private static thistype array thisArray
private static integer count = 0
private static timer t = CreateTimer()
//methods
static method createXYZ takes real x, real y, real z returns thistype
local thistype this = thistype.create()
set thisArray[count] = this
set this.x = x
set this.y = y
set this.z = z
set this.direction = vector.create(1,0,0)
set this.hitGroup = CreateGroup()
set this.passThrough = false
set lastMissileCreated = this
if count == 0 then
call TimerStart(t, TimerInterval, true, function thistype.iterate)
endif
set count = count + 1
return this
endmethod
method setRotation takes real anglexy, real anglexz returns nothing
set this.direction.z =SinBJ(anglexz)
set this.direction.x = CosBJ(anglexy)*CosBJ(anglexz)
set this.direction.y = SinBJ(anglexy)*CosBJ(anglexz)
endmethod
method setOwner takes unit owner returns nothing
set this.owner = owner
endmethod
method setTarget takes unit target returns nothing
set this.target = target
endmethod
method setHitProperties takes real hitrad, real hitzoffset returns nothing
set this.hitrad = hitrad
set this.hitZoffset = hitzoffset
endmethod
method setModel takes string modelPath returns nothing
set this.model = AddSpecialEffect(modelPath,this.x,this.y)
call BlzSetSpecialEffectZ(this.model,this.z)
endmethod
method setModelEffect takes effect e returns nothing
set this.model = e
endmethod
method setVelocity takes real velocity returns nothing
set this.velocity = velocity
endmethod
method setDistance takes real distance returns nothing
set this.distance = distance
endmethod
method setTurnRate takes real turnrate returns nothing
set this.turnrate = turnrate
endmethod
method setFilter takes boolexpr filter returns nothing
set this.filter = filter
endmethod
method setHitTrig takes trigger t returns nothing
set this.HitTrig = t
endmethod
method setMissileType takes boolean isFUHit, boolean isHoming returns nothing
set this.FUHit = isFUHit
set this.homing = isHoming
endmethod
method setPassThrough takes boolean pt returns nothing
set this.passThrough = pt
endmethod
method setOthers takes boolean isClipping, boolean willDrop returns nothing
set this.clipping = isClipping
set this.willDrop = willDrop
endmethod
private method destroyt takes integer i returns nothing
call DestroyGroup(this.hitGroup)
call DestroyEffect(this.model)
call this.direction.destroy()
call this.destroy()
set thisArray[i] = thisArray[count - 1]
set count = count - 1
if count == 0 then
call PauseTimer(t)
endif
endmethod
private method calculateAngle takes nothing returns nothing //this method is only for homing type missiles
local vector targetVector = vector.create(this.tx-this.x,this.ty-this.y,this.tz-this.z)
local vector rotationAxis
if vector.getAngle(this.direction,targetVector) > this.turnrate* bj_DEGTORAD then
set rotationAxis = vector.crossProduct(this.direction,targetVector)
if rotationAxis.getLength() == 0 then
set rotationAxis.x = GetRandomReal(-1,1)
set rotationAxis.y = GetRandomReal(-1,1)
set rotationAxis.z = GetRandomReal(-1,1)
endif
call this.direction.rotate(rotationAxis,this.turnrate* bj_DEGTORAD)
call rotationAxis.destroy()
else
call targetVector.setLength(1)
set this.direction.x = targetVector.x
set this.direction.y = targetVector.y
set this.direction.z = targetVector.z
endif
call targetVector.destroy()
endmethod
private method rotateModel takes nothing returns nothing
local real angleXY = Atan2(this.direction.y,this.direction.x)
local real distXY = SquareRoot(this.direction.x*this.direction.x+this.direction.y*this.direction.y)
local real angleXZ = Atan2(this.direction.z,distXY)
call BlzSetSpecialEffectYaw(this.model,angleXY)
call BlzSetSpecialEffectPitch(this.model,-angleXZ)
//call BlzSetSpecialEffectOrientation(this.model, angleXY, -angleXZ,0)
endmethod
private method moveMissile takes nothing returns nothing
set this.x = this.x + this.direction.x*this.velocity
set this.y = this.y + this.direction.y*this.velocity
set this.z = this.z + this.direction.z*this.velocity
call BlzSetSpecialEffectPosition(this.model,this.x,this.y,this.z)
endmethod
private method checkHit takes integer i returns boolean
local unit u
local integer j
local real lastTargetDis
local real distXY
local unit target = null
if this.passThrough and FirstOfGroup(this.hitGroup) != null then
set j = 0
loop
set u = BlzGroupUnitAt(this.hitGroup,j)
exitwhen u == null
if SquareRoot(Pow(GetUnitX(u)-this.x,2)+Pow(GetUnitY(u)-this.y,2)+Pow(BlzGetUnitZ(u)+GetUnitFlyHeight(u)-this.z,2)) > this.hitrad then
call GroupRemoveUnit(this.hitGroup,u)
endif
set j = j + 1
endloop
endif
if this.FUHit then
set lastMissileX = this.x
set lastMissileY = this.y
set lastMissileZ = this.z
set lastMissileOwner = this.owner
set lastMissileAngleXY = Atan2BJ(this.direction.y,this.direction.x)
set distXY = SquareRoot(this.direction.x*this.direction.x+this.direction.y*this.direction.y)
set lastMissileAngleXZ = -Atan2BJ(this.direction.z,distXY)
call GroupEnumUnitsInRange(g,this.x,this.y,this.hitrad,this.filter)
loop
set u = FirstOfGroup(g)
exitwhen u == null
if SquareRoot(Pow(GetUnitX(u)-lastMissileX,2)+Pow(GetUnitY(u)-lastMissileY,2)+Pow(BlzGetUnitZ(u)+GetUnitFlyHeight(u)-lastMissileZ,2)) <= this.hitrad /*
*/and not IsUnitInGroup(u,this.hitGroup)then
if target == null then
set target = u
set lastTargetDis = SquareRoot((GetUnitX(u)-this.x)*(GetUnitX(u)-this.x)+(GetUnitY(u)-this.y)*(GetUnitY(u)-this.y))
elseif SquareRoot((GetUnitX(u)-this.x)*(GetUnitX(u)-this.x)+(GetUnitY(u)-this.y)*(GetUnitY(u)-this.y)+Pow(BlzGetUnitZ(u)+GetUnitFlyHeight(u)-this.z,2)) < lastTargetDis then
set target = u
set lastTargetDis = SquareRoot((GetUnitX(u)-this.x)*(GetUnitX(u)-this.x)+(GetUnitY(u)-this.y)*(GetUnitY(u)-this.y)+Pow(BlzGetUnitZ(u)+GetUnitFlyHeight(u)-this.z,2))
endif
endif
call GroupRemoveUnit(g,u)
endloop
if target != null then
call GroupAddUnit(this.hitGroup, target)
set lastMissileTarget = target
set target = null
call TriggerExecute(this.HitTrig)
return true
endif
endif
if this.homing and SquareRoot(Pow(GetUnitX(this.target)-this.x,2) + Pow(GetUnitY(this.target)-this.y,2) + Pow(BlzGetUnitZ(this.target)+GetUnitFlyHeight(this.target)-this.z,2)) < this.hitrad /*
*/and not IsUnitInGroup(this.target, this.hitGroup) then
call GroupEnumUnitsInRange(g,this.x,this.y,this.hitrad,this.filter)
if IsUnitInGroup(this.target,g) then
call GroupAddUnit(this.hitGroup, this.target)
//execute trigger
set lastMissileX = this.x
set lastMissileY = this.y
set lastMissileZ = this.z
set lastMissileAngleXY = Atan2BJ(this.direction.y,this.direction.x)
set distXY = SquareRoot(this.direction.x*this.direction.x+this.direction.y*this.direction.y)
set lastMissileAngleXZ = -Atan2BJ(this.direction.z,distXY)
set lastMissileOwner = this.owner
set lastMissileTarget = this.target
call TriggerExecute(this.HitTrig)
return true
endif
endif
return false
endmethod
private static method iterate takes nothing returns nothing
local integer i
local location loc
local thistype this
set i = 0
loop
exitwhen i >= count
set this = thisArray[i]
//if missile is homing
if this.homing then
set this.tx = GetUnitX(this.target)
set this.ty = GetUnitY(this.target)
set this.tz = BlzGetUnitZ(this.target)+GetUnitFlyHeight(this.target)+this.hitZoffset
endif
call this.calculateAngle()
call this.rotateModel()
set loc = Location(this.x,this.y)
if this.checkHit(i) and not this.passThrough then
call this.destroyt(i)
elseif this.distance <= 0 or (this.clipping and (this.z <= GetLocationZ(loc)))then
call this.destroyt(i)
else
call this.moveMissile()
//set new distance left
set this.distance = this.distance - velocity
set i = i + 1
endif
call RemoveLocation(loc)
endloop
set loc = null
endmethod
endstruct
////////////////////////////functions to use
function CreateMissileHomingFUHsfx takes unit owner, unit target, effect model, real angle, real velocity, real turnrate, real maxDis, real hitRad, trigger Action, boolexpr condition, boolean isDropping returns nothing
local Missile m = Missile.createXYZ(BlzGetLocalSpecialEffectX(model),BlzGetLocalSpecialEffectY(model),BlzGetLocalSpecialEffectZ(model))
call m.setModelEffect(model)
call m.setOwner(owner)
call m.setTarget(target)
call m.setTurnRate(turnrate*TimerInterval)
call m.setRotation(angle,0)
call m.setVelocity(velocity)
call m.setMissileType(true,true)
call m.setDistance( maxDis)
call m.setHitProperties(hitRad,GetRandomReal(0.0,hitRad))
call m.setHitTrig(Action)
call m.setFilter(condition)
call m.setOthers(true,false)
endfunction
function CreateMissileFUH2clip takes unit owner, string model, real cx, real cy, real cz, real angleXZ, real angleXY, real velocity, real dis, real hitrad, boolean drop, trigger Action, boolexpr condition returns nothing
local Missile m = Missile.createXYZ(cx,cy,cz)
local effect e = AddSpecialEffect(model, cx, cy)
call BlzSetSpecialEffectYaw(e, Deg2Rad(angleXY))
call BlzSetSpecialEffectZ(e, cz)
call m.setModelEffect(e)
call m.setOwner(owner)
call m.setTurnRate(0)
call m.setRotation(angleXY,angleXZ)
call m.setVelocity(velocity)
call m.setMissileType(true,false)//fuhit = true, homing = false
call m.setDistance(dis)
call m.setHitTrig(Action)
call m.setFilter(condition)
call m.setHitProperties(hitrad,GetRandomReal(0.0,hitrad))
call m.setOthers(true,drop)
//ref leaks
set e = null
endfunction
////////////////////////////////////////////////
endlibrary