1. /* 4 Packages included..
  2. Projectile superclass
  3. TimedBlasts (main system)
  4. Kamehameha (2d example of TimedBlasts System)
  5. AngryKame (3d example of TimedBlasts System
  6. TimedBlasts attempts to give a system to create various "timed blasts" that can be customized to create tons of different spells that follow the general layout
  7. User begins channeling animation, creating the projectile near them..
  8. after a certain size is reached, the projectile is launched to the target point inflicting damage.
  9. 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.
  10. *visual example of what this code attempts to achieve in the case of a 3d clashable blast https://www.youtube.com/watch?v=M7i5Z3C5ZOk
  11. *note clashable and 3d hasn't been tested/made yet*
  12. protected real impactAoe - size of aoe for damage to be done
  13. protected real damage - damage to be done
  14. protected real endScale - final scale of the blast before launching
  15. protected boolean trailOn - creates a trail following the blast as it flies to the target
  16. protected boolean dustOn - creates a dust effect around the caster as he fires
  17. protected boolean pulseOn - makes the missile pulsate as it flies to the targeted area
  18. protected boolean launchOn - creates a launch effect as the missile is launched
  19. protected boolean dropOn - if the missile is fired from an aerial position, the missile is lowered to the targetted area
  20. protected boolean flightOn - if the missile will be fired from an aerial position
  21. protected string trailSFX - specify what SFX will be used for the trail
  22. protected string pulseSFX - specify what SFX will be used for the pulse
  23. protected string launchSFX - " "
  24. protected string finalSFX - " "
  25. protected string dustSFX - " "
  26. protected real trailSize - size of trail created
  27. protected real pulseSize - size of pulses
  28. protected real launchSize - size of launch
  29. protected colorA missileCol - color of missile
  30. protected colorA trailCol = color of trail
  31. protected colorA pulseCol = color of pulse
  32. protected real speed - speed of missile during travel
  33. protected int channelIndex - animation index to channel
  34. protected int launchIndex - animation index to launch
  35. protected real offsetDistance = 50 - small offset from caster
  36. protected real realDropSpeed = -15 if there is a drop, reasonable dropspeed, can be changed
  37. private real timeSinceLastTrail = 0 - used to create trail
  38. private real timeSinceLastPulse = 0 - used to create pulses
  39. private real timeSinceLastChannel = 0 - uses to create channel
  40. protected real timeDistance - how long trails and pulses should last, depends on speed, and missile sizes, should be configured to each spell accordingly
  41. protected sound throwSound = generic missile size
  42. protected real lowerRate = 150. speed that a missile will lower if it is a 3d missile
  43. protected real destroyExplode = 1.5 how long the destruction sfx will be played
  44. protected boolean clashing - setting if the missile is ready to clash
  45. protected boolean clashable - saves true value for clashable until channeling is complete
  46. protected boolean clashed - if a missile has clashed, prevents further clashs
  47. protected boolean channeling = if a missile is still channeling, it cannot clash yet
  48. */
  49. package Projectile
  50. import public Entity
  51. public class Projectile extends FxEntity
  52. // Angles
  53. protected angle xyAngle
  54. private vec3 startpos
  55. private boolean timed = false
  56. private boolean ranged = false
  57. // Moving Speed
  58. private real speed = 0
  59. private real acc = 1.0
  60. protected real dist = 0
  61. private real maxDist = 0
  62. protected real lifespan = 0
  63. protected real dropSpeed = 0
  64. construct( vec3 pos, real radius, player owner, angle xyAngle, string fxpath )
  65. super(pos, radius, owner, xyAngle, fxpath)
  66. startpos = pos
  67. setXYAngle(xyAngle)
  68. active = false
  69. function setRanged(real maxDistance)
  70. this.maxDist = maxDistance*maxDistance
  71. ranged = true
  72. function setTimed(real lifespan)
  73. this.lifespan = lifespan
  74. timed = true
  75. function setSpeed(real speed)
  76. this.speed = speed
  77. //angle.direction(real distance)
  78. setVel(vec3(xyAngle.cos()*speed, xyAngle.sin()*speed, dropSpeed))
  79. function setSpeed(real speed, real drop)
  80. this.speed = speed
  81. //angle.direction(real distance)
  82. setVel(vec3(xyAngle.cos()*speed, xyAngle.sin()*speed, drop))
  83. function setAcc(real factor)
  84. this.acc = factor
  85. function getSpeed() returns real
  86. return speed
  87. function setXYAngle(angle xyA)
  88. this.xyAngle = xyA
  89. fx.setXYAngle(xyA)
  90. function setZAngle(angle zA)
  91. fx.setZAngle(zA)
  92. override function update()
  93. vel *= acc
  94. pos += vel
  95. fixPos()
  96. if timed
  97. lifespan -= ANIMATION_PERIOD
  98. if lifespan <= 0
  99. done = true
  100. return
  101. if ranged
  102. if startpos.distToVecSquared(pos) > maxDist
  103. done = true
  104. package TimedBlasts
  105. import Projectile
  106. import LinkedListModule
  107. import Fx
  108. import Constants
  109. import ClosureTimers
  110. import Terrain
  111. import LinkedList
  112. public class TimedBlasts extends Projectile
  113. use LinkedListModule
  114. //Editable values
  115. protected real impactAoe
  116. protected real damage
  117. protected real endScale
  118. protected boolean trailOn = false
  119. protected boolean dustOn = false
  120. protected boolean pulseOn = false
  121. protected boolean launchOn = false
  122. protected boolean dropOn = false
  123. protected boolean flightOn = true
  124. protected string trailSFX
  125. protected string pulseSFX
  126. protected string launchSFX
  127. protected string finalSFX
  128. protected string dustSFX = dustWave
  129. protected real trailSize
  130. protected real pulseSize
  131. protected real launchSize
  132. protected colorA missileCol = colorA(255,255,255,255)
  133. protected colorA trailCol = colorA(255,255,255,255)
  134. protected colorA pulseCol = colorA(255,255,255,255)
  135. protected real speed
  136. protected int channelIndex
  137. protected int launchIndex
  138. protected real offsetDistance = 50
  139. protected real realDropSpeed = -15
  140. private real timeSinceLastTrail = 0
  141. private real timeSinceLastPulse = 0
  142. private real timeSinceLastChannel = 0
  143. protected real timeDistance = 1
  144. protected sound throwSound = gg_snd_kamehameha_fire
  145. protected real lowerRate = 150.
  146. protected real destroyExplode = 1.5
  147. protected boolean clashing = false
  148. protected boolean clashable = false
  149. protected boolean clashed = false
  150. protected boolean channeling = false
  151. protected LinkedList<Fx> trailList = new LinkedList<Fx>()
  152. //Instance Variables
  153. private vec3 target
  154. protected unit u
  155. private timer t = getTimer()
  156. protected real scale
  157. protected angle targetAngle
  158. private boolean missileCast = false
  159. construct(unit actor,vec3 pos, player owner, vec3 target, string SFX, real originalScale)
  160. super(pos.addReals(0, 0, pos.withTerrainZ().z), 0, owner, pos.angleTo2d(target), SFX)
  161. this.targetAngle = pos.angleTo2d(target)
  162. this.u = actor
  163. this.target = target
  164. this.u.pause()
  165. this.scale = originalScale
  166. function startMissile()
  167. this.setSpeed(0)
  168. this.pos = pos.offset2d(pos.angleTo2d(target), offsetDistance)
  169. this.pos.z += 50
  170. this.fixPos()
  171. this.fx.setColor(missileCol)
  172. this.fx.setScale(this.scale)
  173. this.t.setData(this castTo int)
  174. this.t.startPeriodic(.1, function callExpandMissile)
  175. //if dust is activated
  176. if this.dustOn
  177. this.createDust()
  178. function createDust()
  179. effect x = AddSpecialEffectTarget(dustSFX, u, "origin")
  180. DestroyEffectBJ(x)
  181. static function callExpandMissile()
  182. (GetExpiredTimer().getData() castTo TimedBlasts).expandMissile()
  183. function expandMissile()
  184. if this.timeSinceLastChannel == 0
  185. this.u.setAnimation(channelIndex)
  186. if this.timeSinceLastChannel >= (.18)
  187. this.u.setAnimation(channelIndex)
  188. this.timeSinceLastChannel -= (.17)
  189. this.timeSinceLastChannel += ANIMATION_PERIOD
  190. this.scale += .05
  191. this.fx.setScale(this.scale)
  192. if this.scale >= endScale
  193. if this.flightOn
  194. this.u.setFlyHeight(0, lowerRate)
  195. if this.launchOn
  196. this.createLaunchFX()
  197. if this.dropOn
  198. this.dropSpeed = realDropSpeed
  199. this.setSpeed(speed)
  200. this.t.release()
  201. this.u.setAnimation(launchIndex)
  202. PlaySoundOnUnitBJ(this.throwSound, 70, this.u)
  203. this.missileCast = true
  204. if not this.channeling
  205. this.u.unpause()
  206. if this.clashing
  207. this.clashable = true
  208. //calculate frequency of trail creation
  209. function createLaunchFX()
  210. Fx launch = new Fx(fx.getPos2(),this.targetAngle, kameLaunch)
  211. launch.setScale(launchSize)
  212. doAfter(.5, () -> destroy launch)
  213. function createTrail()
  214. Fx trail = new Fx(fx.getPos3d(), this.targetAngle, trailSFX)
  215. ..setScale(trailSize)
  216. ..setColor(trailCol)
  217. if flightOn == false
  218. trail.setZ(100)
  219. // doAfter(timeDistance, () -> trail.hiddenDestroy())
  220. this.trailList.add(trail)
  221. function createPulse()
  222. Fx pulse = new Fx(fx.getPos3d(), this.targetAngle, pulseSFX)
  223. ..setScale(pulseSize)
  224. ..setZAngle(-5200)
  225. ..setColor(pulseCol)
  226. if this.flightOn == false
  227. pulse.setZ(100)
  228. // pulse.getDummy().setAnimation(0)
  229. doAfter(timeDistance, () -> pulse.hiddenDestroy())
  230. override function update()
  231. super.update()
  232. //should be speed dependent at some level.
  233. if pos.toVec2().distToVecSquared(target.toVec2()) < 120*120
  234. //timeDistance = 0.15
  235. if this.getSpeed() > 0
  236. if this.trailOn
  237. if this.timeSinceLastTrail > (2/speed)
  238. this.createTrail()
  239. this.timeSinceLastTrail -= (2/speed)
  240. this.timeSinceLastTrail += ANIMATION_PERIOD
  241. if this.pulseOn
  242. if this.timeSinceLastPulse > (2/speed)
  243. this.createPulse()
  244. this.timeSinceLastPulse -= (2/speed)
  245. this.timeSinceLastPulse += ANIMATION_PERIOD
  246. if not this.clashed
  247. if this.clashable
  248. Entity e = Entity.getFirst()
  249. while e != null
  250. if e!= this and this.owner != e.owner
  251. if this.owner.isAllyOf(e.owner)
  252. TimedBlasts blast2 = e castTo TimedBlasts
  253. if blast2.clashable and not blast2.clashed
  254. if this.pos.distToVecSquared(e.pos) < 40000.
  255. print(this.pos.distToVecSquared(e.pos).toString())
  256. if this.pos.distToVecSquared(e.pos) < (120*120)
  257. //print("hi6!")
  258. this.onHit(blast2)
  259. e=e.next
  260. if ((this.u.getPos().distToVecSquared(target.toVec2()) < 150*150) or (pos.toVec2().distToVecSquared(target.toVec2()) < 64*64)) and missileCast
  261. for unit enemy from ENUM_GROUP..enumUnitsInRange(pos.toVec2(), impactAoe)
  262. if enemy.isEnemy(owner)
  263. this.u.damageTarget(enemy, damage)
  264. done = true
  265. terminate()
  266. function onHit(TimedBlasts blast2)
  267. boolean winner1 = false
  268. boolean winner2 = false
  269. //print("hi7!")
  270. this.clashed = true
  271. blast2.clashed = true
  272. blast2.setSpeed(0)
  273. this.setSpeed(0)
  274. blast2.active = false
  275. this.active = false
  276. //this.fx.setScale(endScale+ 1)
  277. //blast2.fx.setScale(endScale+ 1)
  278. doPeriodically(.25, (CallbackPeriodic cb) -> begin
  279. Fx effect1 = new Fx(fx.getPos2(),this.targetAngle, iceNova)
  280. ..setScale(1.8)
  281. ..setZ(100)
  282. ..setZAngle(-5200)
  283. Fx effect2 = new Fx(blast2.fx.getPos2(),this.targetAngle, iceNova)
  284. ..setScale(1.8)
  285. ..setZ(100)
  286. ..setZAngle(-5200)
  287. Fx effect5 = new Fx(((fx.getPos2() + blast2.fx.getPos2()) *.5).toVec3().addReals(0, 0, 50), this.targetAngle, sparklyExplosion)
  288. ..setScale(5)
  289. doAfter(.25, () -> begin
  290. destroy(effect1)
  291. destroy(effect2)
  292. destroy(effect5)
  293. end)
  294. if this.u.getMana() == 0
  295. winner2 = true
  296. if blast2.u.getMana() == 0
  297. winner1 = true
  298. this.u.setMana(u.getMana()-1)
  299. blast2.u.setMana(blast2.u.getMana()-2)
  300. if winner1
  301. print(this.u.getName())
  302. blast2.terminate()
  303. this.target = blast2.u.getPos3()
  304. this.setSpeed(this.speed)
  305. this.active = true
  306. destroy cb
  307. if winner2 and not winner1
  308. print(blast2.u.getName())
  309. terminate()
  310. blast2.target = this.u.getPos3()
  311. blast2.setSpeed(blast2.speed)
  312. blast2.active = true
  313. destroy cb
  314. end)
  315. ondestroy
  316. if this.channeling
  317. this.u.unpause()
  318. Fx final = new Fx(fx.getPos3d(), this.targetAngle, finalSFX)
  319. final.setScale(2)
  320. doAfter(destroyExplode, () -> final.hiddenDestroy())
  321. for i = 0 to (this.trailList.getSize() -1)
  322. this.trailList.get(i).hiddenDestroy()
  323. this.done = true
  324. package Kamehameha
  325. import Constants
  326. import TimedBlasts
  327. constant real originalScale = .2
  328. public class Kamehameha extends TimedBlasts
  329. construct(unit actor,vec3 pos, player owner, vec3 target, int level)
  330. super(actor,pos.addReals(0, 0, 50),owner,target,bigKamehamehaBall,originalScale)
  331. //if (actor.getTypeId() == 'H001')
  332. this.impactAoe = 500
  333. this.damage = 150*level.toReal() + (GetHeroInt(actor, true)*10)
  334. this.trailOn = true
  335. this.dustOn = true
  336. this.pulseOn = true
  337. this.launchOn = true
  338. int actorID = actor.getTypeId()
  339. if actorID == 'H000'
  340. this.channelIndex = 11
  341. this.launchIndex = 12
  342. this.throwSound = gg_snd_Kamehameha_Voice
  343. if actorID == 'H005' or actorID == 'H009'
  344. this.channelIndex = 20
  345. this.launchIndex = 18
  346. if actorID == 'H00A'
  347. this.channelIndex = 5
  348. this.launchIndex = 4
  349. if actorID == 'H001' or actorID == 'H008'
  350. this.channelIndex = 7
  351. this.launchIndex = 8
  352. this.throwSound = gg_snd_GohanKame
  353. if actorID == 'H00D' or actorID == 'H00E' or actorID == 'H00F'
  354. this.channelIndex = 8
  355. this.launchIndex = 12
  356. if actorID == 'H007'
  357. this.channelIndex = 9
  358. this.launchIndex = 13
  359. if actorID == 'H00G'
  360. this.channelIndex = 12
  361. this.launchIndex = 11
  362. this.speed = 32
  363. this.endScale = .6
  364. this.trailSFX = bigKamehamehaBall
  365. this.trailSize = .3
  366. this.pulseSFX = bluePulse
  367. this.launchSFX = kameLaunch
  368. this.launchSize = 5
  369. this.finalSFX = bigBlueExplosion
  370. this.pulseSize = 1
  371. this.trailCol = colorA(255,255,255,255)
  372. this.clashing = true
  373. this.channeling = true
  374. startMissile()
  375. package AngryKame
  376. import Constants
  377. import TimedBlasts
  378. import ClosureTimers
  379. constant real originalScale = .2
  380. public class AngryKame extends TimedBlasts
  381. construct(unit actor,vec3 pos, player owner, vec3 target, int level)
  382. super(actor,pos.addReals(0, 0, 700),owner,target,dummy2,originalScale)
  383. this.impactAoe = 500
  384. actor.setFlyHeight(700, 700.)
  385. this.flightOn = true
  386. this.dropOn = true
  387. this.offsetDistance = 0
  388. this.missileCol = colorA(150,150,0,255)
  389. this.speed = 25
  390. this.endScale = 1.5
  391. this.dustSFX = dustWave
  392. this.damage = 5000*level.toReal() + (GetHeroInt(actor, true)*20)
  393. this.finalSFX = nuclearExplosion
  394. this.trailOn = true
  395. this.dustOn = true
  396. this.pulseOn = true
  397. this.launchOn = false
  398. this.channelIndex = 20
  399. this.launchIndex = 10
  400. this.trailSFX = pinkBall
  401. this.trailSize = .6
  402. this.launchSFX = kameLaunch
  403. this.launchSize = 5
  404. this.trailCol = colorA(150,150,0,255)
  405. this.lowerRate = 300.
  406. this.realDropSpeed = -25
  407. this.destroyExplode = 3
  408. this.pulseSFX = windBlue
  409. this.pulseSize = 1.2
  410. this.pulseCol = colorA(150,150,0,255)
  411. effect x = AddSpecialEffectTarget(kamelightning, u, "origin")
  412. doAfter(1.5, () -> begin
  413. doAfter(1, () -> begin
  414. PlaySoundOnUnitBJ(gg_snd_angrykame, 70, this.u)
  415. end)
  416. startMissile()
  417. fx.setFx(pinkBall)
  418. end)
  419. doAfter(12, () -> begin
  420. DestroyEffectBJ(x)
  421. end)

goto line:
Compare with:
text copy window edit this code post new code