/* 4 Packages included..Projectile superclassTimedBlasts (main system)Kamehameha (2d example of TimedBlasts System)AngryKame (3d example of TimedBlasts SystemTimedBlasts attempts to give a system to create various "timed blasts" that can be customized to create tons of different spells that follow the general layoutUser begins channeling animation, creating the projectile near them..after a certain size is reached, the projectile is launched to the target point inflicting damage.If two "clashable" blasts hit each other, the two casters will be in a struggle until one runs out of mana, and the winning blast will change target to its opposing caster unit.*visual example of what this code attempts to achieve in the case of a 3d clashable blast https://www.youtube.com/watch?v=M7i5Z3C5ZOk*note clashable and 3d hasn't been tested/made yet* protected real impactAoe - size of aoe for damage to be done protected real damage - damage to be done protected real endScale - final scale of the blast before launching protected boolean trailOn - creates a trail following the blast as it flies to the target protected boolean dustOn - creates a dust effect around the caster as he fires protected boolean pulseOn - makes the missile pulsate as it flies to the targeted area protected boolean launchOn - creates a launch effect as the missile is launched protected boolean dropOn - if the missile is fired from an aerial position, the missile is lowered to the targetted area protected boolean flightOn - if the missile will be fired from an aerial position protected string trailSFX - specify what SFX will be used for the trail protected string pulseSFX - specify what SFX will be used for the pulse protected string launchSFX - " " protected string finalSFX - " " protected string dustSFX - " " protected real trailSize - size of trail created protected real pulseSize - size of pulses protected real launchSize - size of launch protected colorA missileCol - color of missile protected colorA trailCol = color of trail protected colorA pulseCol = color of pulse protected real speed - speed of missile during travel protected int channelIndex - animation index to channel protected int launchIndex - animation index to launch protected real offsetDistance = 50 - small offset from caster protected real realDropSpeed = -15 if there is a drop, reasonable dropspeed, can be changed private real timeSinceLastTrail = 0 - used to create trail private real timeSinceLastPulse = 0 - used to create pulses private real timeSinceLastChannel = 0 - uses to create channel protected real timeDistance - how long trails and pulses should last, depends on speed, and missile sizes, should be configured to each spell accordingly protected sound throwSound = generic missile size protected real lowerRate = 150. speed that a missile will lower if it is a 3d missile protected real destroyExplode = 1.5 how long the destruction sfx will be played protected boolean clashing - setting if the missile is ready to clash protected boolean clashable - saves true value for clashable until channeling is complete protected boolean clashed - if a missile has clashed, prevents further clashs protected boolean channeling = if a missile is still channeling, it cannot clash yet*/package Projectile
importpublic Entity
publicclass Projectile extends FxEntity
// Anglesprotected angle xyAngle
private vec3 startpos
privateboolean timed =falseprivateboolean ranged =false// Moving Speedprivatereal speed =0privatereal acc =1.0protectedreal dist =0privatereal maxDist =0protectedreal lifespan =0protectedreal dropSpeed =0construct( vec3 pos,real radius,player owner, angle xyAngle,string fxpath )
super(pos, radius, owner, xyAngle, fxpath)
startpos = pos
setXYAngle(xyAngle)
active =falsefunction setRanged(real maxDistance)this.maxDist = maxDistance*maxDistance
ranged =truefunction setTimed(real lifespan)this.lifespan = lifespan
timed =truefunction setSpeed(real speed)this.speed = speed
//angle.direction(real distance)
setVel(vec3(xyAngle.cos()*speed, xyAngle.sin()*speed, dropSpeed))function setSpeed(real speed,real drop)this.speed = speed
//angle.direction(real distance)
setVel(vec3(xyAngle.cos()*speed, xyAngle.sin()*speed, drop))function setAcc(real factor)this.acc = factor
function getSpeed()returnsrealreturn speed
function setXYAngle(angle xyA)this.xyAngle = xyA
fx.setXYAngle(xyA)function setZAngle(angle zA)
fx.setZAngle(zA)overridefunction update()
vel *= acc
pos += vel
fixPos()if timed
lifespan -= ANIMATION_PERIOD
if lifespan <=0
done =truereturnif ranged
if startpos.distToVecSquared(pos) > maxDist
done =truepackage TimedBlasts
import Projectile
import LinkedListModule
import Fx
import Constants
import ClosureTimers
import Terrain
import LinkedList
publicclass TimedBlasts extends Projectile
use LinkedListModule
//Editable valuesprotectedreal impactAoe
protectedreal damage
protectedreal endScale
protectedboolean trailOn =falseprotectedboolean dustOn =falseprotectedboolean pulseOn =falseprotectedboolean launchOn =falseprotectedboolean dropOn =falseprotectedboolean flightOn =trueprotectedstring trailSFX
protectedstring pulseSFX
protectedstring launchSFX
protectedstring finalSFX
protectedstring dustSFX = dustWave
protectedreal trailSize
protectedreal pulseSize
protectedreal launchSize
protected colorA missileCol = colorA(255,255,255,255)protected colorA trailCol = colorA(255,255,255,255)protected colorA pulseCol = colorA(255,255,255,255)protectedreal speed
protectedint channelIndex
protectedint launchIndex
protectedreal offsetDistance =50protectedreal realDropSpeed =-15privatereal timeSinceLastTrail =0privatereal timeSinceLastPulse =0privatereal timeSinceLastChannel =0protectedreal timeDistance =1protectedsound throwSound = gg_snd_kamehameha_fire
protectedreal lowerRate =150.
protectedreal destroyExplode =1.5protectedboolean clashing =falseprotectedboolean clashable =falseprotectedboolean clashed =falseprotectedboolean channeling =falseprotected LinkedList<Fx> trailList =new LinkedList<Fx>()//Instance Variablesprivate vec3 target
protectedunit u
privatetimer t = getTimer()protectedreal scale
protected angle targetAngle
privateboolean missileCast =falseconstruct(unit actor,vec3 pos,player owner, vec3 target,string SFX,real originalScale)
super(pos.addReals(0,0, pos.withTerrainZ().z),0, owner, pos.angleTo2d(target), SFX)this.targetAngle = pos.angleTo2d(target)this.u = actor
this.target = target
this.u.pause()this.scale = originalScale
function startMissile()this.setSpeed(0)this.pos = pos.offset2d(pos.angleTo2d(target), offsetDistance)this.pos.z +=50this.fixPos()this.fx.setColor(missileCol)this.fx.setScale(this.scale)this.t.setData(thiscastToint)this.t.startPeriodic(.1,function callExpandMissile)//if dust is activatedifthis.dustOn
this.createDust()function createDust()effect x =AddSpecialEffectTarget(dustSFX, u,"origin")DestroyEffectBJ(x)staticfunction callExpandMissile()(GetExpiredTimer().getData()castTo TimedBlasts).expandMissile()function expandMissile()ifthis.timeSinceLastChannel ==0this.u.setAnimation(channelIndex)ifthis.timeSinceLastChannel >=(.18)this.u.setAnimation(channelIndex)this.timeSinceLastChannel -=(.17)this.timeSinceLastChannel += ANIMATION_PERIOD
this.scale += .05this.fx.setScale(this.scale)ifthis.scale >= endScale
ifthis.flightOn
this.u.setFlyHeight(0, lowerRate)ifthis.launchOn
this.createLaunchFX()ifthis.dropOn
this.dropSpeed = realDropSpeed
this.setSpeed(speed)this.t.release()this.u.setAnimation(launchIndex)PlaySoundOnUnitBJ(this.throwSound,70,this.u)this.missileCast =trueifnotthis.channeling
this.u.unpause()ifthis.clashing
this.clashable =true//calculate frequency of trail creationfunction createLaunchFX()
Fx launch =new Fx(fx.getPos2(),this.targetAngle, kameLaunch)
launch.setScale(launchSize)
doAfter(.5,()-> destroy launch)function createTrail()
Fx trail =new Fx(fx.getPos3d(),this.targetAngle, trailSFX)
..setScale(trailSize)
..setColor(trailCol)if flightOn ==false
trail.setZ(100)// doAfter(timeDistance, () -> trail.hiddenDestroy())this.trailList.add(trail)function createPulse()
Fx pulse =new Fx(fx.getPos3d(),this.targetAngle, pulseSFX)
..setScale(pulseSize)
..setZAngle(-5200)
..setColor(pulseCol)ifthis.flightOn ==false
pulse.setZ(100)// pulse.getDummy().setAnimation(0)
doAfter(timeDistance,()-> pulse.hiddenDestroy())overridefunction update()
super.update()//should be speed dependent at some level.if pos.toVec2().distToVecSquared(target.toVec2()) < 120*120//timeDistance = 0.15ifthis.getSpeed() > 0ifthis.trailOn
ifthis.timeSinceLastTrail > (2/speed)this.createTrail()this.timeSinceLastTrail -=(2/speed)this.timeSinceLastTrail += ANIMATION_PERIOD
ifthis.pulseOn
ifthis.timeSinceLastPulse > (2/speed)this.createPulse()this.timeSinceLastPulse -=(2/speed)this.timeSinceLastPulse += ANIMATION_PERIOD
ifnotthis.clashed
ifthis.clashable
Entity e = Entity.getFirst()while e !=nullif e!=thisandthis.owner != e.owner
ifthis.owner.isAllyOf(e.owner)
TimedBlasts blast2 = e castTo TimedBlasts
if blast2.clashable andnot blast2.clashed
ifthis.pos.distToVecSquared(e.pos) < 40000.
print(this.pos.distToVecSquared(e.pos).toString())ifthis.pos.distToVecSquared(e.pos) < (120*120)//print("hi6!")this.onHit(blast2)
e=e.next
if((this.u.getPos().distToVecSquared(target.toVec2()) < 150*150)or(pos.toVec2().distToVecSquared(target.toVec2()) < 64*64))and missileCast
forunit enemy from ENUM_GROUP..enumUnitsInRange(pos.toVec2(), impactAoe)if enemy.isEnemy(owner)this.u.damageTarget(enemy, damage)
done =true
terminate()function onHit(TimedBlasts blast2)boolean winner1 =falseboolean winner2 =false//print("hi7!")this.clashed =true
blast2.clashed =true
blast2.setSpeed(0)this.setSpeed(0)
blast2.active =falsethis.active =false//this.fx.setScale(endScale+ 1)//blast2.fx.setScale(endScale+ 1)
doPeriodically(.25,(CallbackPeriodic cb)-> begin
Fx effect1 =new Fx(fx.getPos2(),this.targetAngle, iceNova)
..setScale(1.8)
..setZ(100)
..setZAngle(-5200)
Fx effect2 =new Fx(blast2.fx.getPos2(),this.targetAngle, iceNova)
..setScale(1.8)
..setZ(100)
..setZAngle(-5200)
Fx effect5 =new Fx(((fx.getPos2()+ blast2.fx.getPos2())*.5).toVec3().addReals(0,0,50),this.targetAngle, sparklyExplosion)
..setScale(5)
doAfter(.25,()-> begindestroy(effect1)destroy(effect2)destroy(effect5)end)ifthis.u.getMana()==0
winner2 =trueif blast2.u.getMana()==0
winner1 =truethis.u.setMana(u.getMana()-1)
blast2.u.setMana(blast2.u.getMana()-2)if winner1
print(this.u.getName())
blast2.terminate()this.target = blast2.u.getPos3()this.setSpeed(this.speed)this.active =truedestroy cb
if winner2 andnot winner1
print(blast2.u.getName())
terminate()
blast2.target =this.u.getPos3()
blast2.setSpeed(blast2.speed)
blast2.active =truedestroy cb
end)ondestroyifthis.channeling
this.u.unpause()
Fx final =new Fx(fx.getPos3d(),this.targetAngle, finalSFX)
final.setScale(2)
doAfter(destroyExplode,()-> final.hiddenDestroy())for i =0to(this.trailList.getSize()-1)this.trailList.get(i).hiddenDestroy()this.done =truepackage Kamehameha
import Constants
import TimedBlasts
constantreal originalScale = .2publicclass Kamehameha extends TimedBlasts
construct(unit actor,vec3 pos,player owner, vec3 target,int level)
super(actor,pos.addReals(0,0,50),owner,target,bigKamehamehaBall,originalScale)//if (actor.getTypeId() == 'H001')this.impactAoe =500this.damage =150*level.toReal()+(GetHeroInt(actor,true)*10)this.trailOn =truethis.dustOn =truethis.pulseOn =truethis.launchOn =trueint actorID = actor.getTypeId()if actorID =='H000'this.channelIndex =11this.launchIndex =12this.throwSound = gg_snd_Kamehameha_Voice
if actorID =='H005'or actorID =='H009'this.channelIndex =20this.launchIndex =18if actorID =='H00A'this.channelIndex =5this.launchIndex =4if actorID =='H001'or actorID =='H008'this.channelIndex =7this.launchIndex =8this.throwSound = gg_snd_GohanKame
if actorID =='H00D'or actorID =='H00E'or actorID =='H00F'this.channelIndex =8this.launchIndex =12if actorID =='H007'this.channelIndex =9this.launchIndex =13if actorID =='H00G'this.channelIndex =12this.launchIndex =11this.speed =32this.endScale = .6this.trailSFX = bigKamehamehaBall
this.trailSize = .3this.pulseSFX = bluePulse
this.launchSFX = kameLaunch
this.launchSize =5this.finalSFX = bigBlueExplosion
this.pulseSize =1this.trailCol = colorA(255,255,255,255)this.clashing =truethis.channeling =true
startMissile()package AngryKame
import Constants
import TimedBlasts
import ClosureTimers
constantreal originalScale = .2publicclass AngryKame extends TimedBlasts
construct(unit actor,vec3 pos,player owner, vec3 target,int level)
super(actor,pos.addReals(0,0,700),owner,target,dummy2,originalScale)this.impactAoe =500
actor.setFlyHeight(700,700.)this.flightOn =truethis.dropOn =truethis.offsetDistance =0this.missileCol = colorA(150,150,0,255)this.speed =25this.endScale =1.5this.dustSFX = dustWave
this.damage =5000*level.toReal()+(GetHeroInt(actor,true)*20)this.finalSFX = nuclearExplosion
this.trailOn =truethis.dustOn =truethis.pulseOn =truethis.launchOn =falsethis.channelIndex =20this.launchIndex =10this.trailSFX = pinkBall
this.trailSize = .6this.launchSFX = kameLaunch
this.launchSize =5this.trailCol = colorA(150,150,0,255)this.lowerRate =300.
this.realDropSpeed =-25this.destroyExplode =3this.pulseSFX = windBlue
this.pulseSize =1.2this.pulseCol = colorA(150,150,0,255)effect x =AddSpecialEffectTarget(kamelightning, u,"origin")
doAfter(1.5,()-> begin
doAfter(1,()-> beginPlaySoundOnUnitBJ(gg_snd_angrykame,70,this.u)end)
startMissile()
fx.setFx(pinkBall)end)
doAfter(12,()-> beginDestroyEffectBJ(x)end)