/* 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
importpublicEntitypublicclass Projectile extends FxEntity
// Anglesprotected angle xyAngle
private vec3 startpos
privateboolean timed = falseprivateboolean ranged = false// Moving Speedprivate real speed = 0private real acc = 1.0protected real dist = 0private real maxDist = 0protected real lifespan = 0protected real dropSpeed = 0
construct( vec3 pos, real radius, player owner, angle xyAngle, string fxpath )super(pos, radius, owner, xyAngle, fxpath)
startpos = pos
setXYAngle(xyAngle)
active = false
function setRanged(real maxDistance)
this.maxDist = maxDistance*maxDistance
ranged = true
function setTimed(real lifespan)
this.lifespan = lifespan
timed = true
function 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() returns real
return speed
function setXYAngle(angle xyA)
this.xyAngle = xyA
fx.setXYAngle(xyA)
function setZAngle(angle zA)
fx.setZAngle(zA)
override function 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
importLinkedListpublicclass TimedBlasts extends Projectile
use LinkedListModule
//Editable valuesprotected real impactAoe
protected real damage
protected real endScale
protectedboolean trailOn = falseprotectedboolean dustOn = falseprotectedboolean pulseOn = falseprotectedboolean launchOn = falseprotectedboolean dropOn = falseprotectedboolean flightOn = trueprotected string trailSFX
protected string pulseSFX
protected string launchSFX
protected string finalSFX
protected string dustSFX = dustWave
protected real trailSize
protected real pulseSize
protected real 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)protected real speed
protectedint channelIndex
protectedint launchIndex
protected real offsetDistance = 50protected real realDropSpeed = -15private real timeSinceLastTrail = 0private real timeSinceLastPulse = 0private real timeSinceLastChannel = 0protected real timeDistance = 1protected sound throwSound = gg_snd_kamehameha_fire
protected real lowerRate = 150.protected real destroyExplode = 1.5protectedboolean clashing = falseprotectedboolean clashable = falseprotectedboolean clashed = falseprotectedboolean channeling = falseprotected LinkedList<Fx> trailList = new LinkedList<Fx>()//Instance Variablesprivate vec3 target
protected unit u
private timer t = getTimer()protected real scale
protected angle targetAngle
privateboolean missileCast = false
construct(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 += 50
this.fixPos()
this.fx.setColor(missileCol)
this.fx.setScale(this.scale)
this.t.setData(this castTo int)
this.t.startPeriodic(.1, function callExpandMissile)//if dust is activatedif this.dustOn
this.createDust()
function createDust()
effect x = AddSpecialEffectTarget(dustSFX, u, "origin")
DestroyEffectBJ(x)static function callExpandMissile()(GetExpiredTimer().getData() castTo TimedBlasts).expandMissile()
function expandMissile()if this.timeSinceLastChannel == 0
this.u.setAnimation(channelIndex)if this.timeSinceLastChannel >= (.18)
this.u.setAnimation(channelIndex)
this.timeSinceLastChannel -= (.17)
this.timeSinceLastChannel += ANIMATION_PERIOD
this.scale += .05
this.fx.setScale(this.scale)if this.scale >= endScale
if this.flightOn
this.u.setFlyHeight(0, lowerRate)if this.launchOn
this.createLaunchFX()if this.dropOn
this.dropSpeed = realDropSpeed
this.setSpeed(speed)
this.t.release()
this.u.setAnimation(launchIndex)
PlaySoundOnUnitBJ(this.throwSound, 70, this.u)
this.missileCast = trueif not this.channeling
this.u.unpause()if this.clashing
this.clashable = true//calculate frequency of trail creation
function 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)if this.flightOn == false
pulse.setZ(100)// pulse.getDummy().setAnimation(0)
doAfter(timeDistance, () -> pulse.hiddenDestroy())
override function update()
super.update()//should be speed dependent at some level.if pos.toVec2().distToVecSquared(target.toVec2()) < 120*120//timeDistance = 0.15if this.getSpeed() > 0if this.trailOn
if this.timeSinceLastTrail > (2/speed)
this.createTrail()
this.timeSinceLastTrail -= (2/speed)
this.timeSinceLastTrail += ANIMATION_PERIOD
if this.pulseOn
if this.timeSinceLastPulse > (2/speed)
this.createPulse()
this.timeSinceLastPulse -= (2/speed)
this.timeSinceLastPulse += ANIMATION_PERIOD
if not this.clashed
if this.clashable
Entity e = Entity.getFirst()while e != nullif e!= this and this.owner != e.owner
if this.owner.isAllyOf(e.owner)
TimedBlasts blast2 = e castTo TimedBlasts
if blast2.clashable and not blast2.clashed
if this.pos.distToVecSquared(e.pos) < 40000.
print(this.pos.distToVecSquared(e.pos).toString())if this.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
for unit 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 = false
this.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, () -> begin
destroy(effect1)
destroy(effect2)
destroy(effect5)
end)if this.u.getMana() == 0
winner2 = trueif blast2.u.getMana() == 0
winner1 = true
this.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 = true
destroy cb
if winner2 and not winner1
print(blast2.u.getName())
terminate()
blast2.target = this.u.getPos3()
blast2.setSpeed(blast2.speed)
blast2.active = true
destroy cb
end)
ondestroy
if this.channeling
this.u.unpause()
Fx final = new Fx(fx.getPos3d(), this.targetAngle, finalSFX)
final.setScale(2)
doAfter(destroyExplode, () -> final.hiddenDestroy())for i = 0 to (this.trailList.getSize() -1)
this.trailList.get(i).hiddenDestroy()
this.done = truepackage Kamehameha
import Constants
import TimedBlasts
constant real 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 = 500
this.damage = 150*level.toReal() + (GetHeroInt(actor, true)*10)
this.trailOn = true
this.dustOn = true
this.pulseOn = true
this.launchOn = trueint actorID = actor.getTypeId()if actorID == 'H000'
this.channelIndex = 11
this.launchIndex = 12
this.throwSound = gg_snd_Kamehameha_Voice
if actorID == 'H005' or actorID == 'H009'
this.channelIndex = 20
this.launchIndex = 18if actorID == 'H00A'
this.channelIndex = 5
this.launchIndex = 4if actorID == 'H001' or actorID == 'H008'
this.channelIndex = 7
this.launchIndex = 8
this.throwSound = gg_snd_GohanKame
if actorID == 'H00D' or actorID == 'H00E' or actorID == 'H00F'
this.channelIndex = 8
this.launchIndex = 12if actorID == 'H007'
this.channelIndex = 9
this.launchIndex = 13if actorID == 'H00G'
this.channelIndex = 12
this.launchIndex = 11
this.speed = 32
this.endScale = .6
this.trailSFX = bigKamehamehaBall
this.trailSize = .3
this.pulseSFX = bluePulse
this.launchSFX = kameLaunch
this.launchSize = 5
this.finalSFX = bigBlueExplosion
this.pulseSize = 1
this.trailCol = colorA(255,255,255,255)
this.clashing = true
this.channeling = true
startMissile()package AngryKame
import Constants
import TimedBlasts
import ClosureTimers
constant real 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 = true
this.dropOn = true
this.offsetDistance = 0
this.missileCol = colorA(150,150,0,255)
this.speed = 25
this.endScale = 1.5
this.dustSFX = dustWave
this.damage = 5000*level.toReal() + (GetHeroInt(actor, true)*20)
this.finalSFX = nuclearExplosion
this.trailOn = true
this.dustOn = true
this.pulseOn = true
this.launchOn = false
this.channelIndex = 20
this.launchIndex = 10
this.trailSFX = pinkBall
this.trailSize = .6
this.launchSFX = kameLaunch
this.launchSize = 5
this.trailCol = colorA(150,150,0,255)
this.lowerRate = 300.
this.realDropSpeed = -25
this.destroyExplode = 3
this.pulseSFX = windBlue
this.pulseSize = 1.2
this.pulseCol = colorA(150,150,0,255)
effect x = AddSpecialEffectTarget(kamelightning, u, "origin")
doAfter(1.5, () -> begin
doAfter(1, () -> begin
PlaySoundOnUnitBJ(gg_snd_angrykame, 70, this.u)
end)
startMissile()
fx.setFx(pinkBall)
end)
doAfter(12, () -> begin
DestroyEffectBJ(x)
end)