Advertisement
A-G-D

TorrentArray

Feb 9th, 2017
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 21.97 KB | None | 0 0
  1. library TorrentArray /*
  2.  
  3.  
  4. */requires /*
  5.  
  6. */TorrentSystem /*
  7. */SpellEffectEvent /*
  8. */SpellEffectUtils /*
  9. */Alloc /*
  10. */Timer /*
  11. */Table /*
  12. */LinkedList /*
  13. */BooleanExpression /*
  14. */ResourcePreloader /*
  15. */MapBounds /*
  16. */Initializer /*
  17.  
  18.  
  19. |---------|
  20. | Credits |
  21. |---------|
  22.  
  23. Author:
  24. - AGD
  25. Dependencies:
  26. - Bribe (SpellEffectEvent, Table)
  27. - Vexorian (TimerUtils)
  28. - Nestharus (WorldBounds)
  29. - AGD (Torrent, ResourcePreloader)
  30.  
  31.  
  32. |-----------|
  33. | Importing |
  34. |-----------|
  35.  
  36. - Import the dummy.mdx model to your map
  37. - Copy the dummy unit and the Torrent ability in Object Editor
  38. - Copy the trigger category containing this script and its dependencies
  39. - Configure the spell's data in the default configuration library or alternatively,
  40. make your own one
  41.  
  42.  
  43. |---------------------|
  44. | Configuration Hints |
  45. |---------------------|
  46.  
  47. The configuration allows you to do many possible tricks. One of these is the trick
  48. that allows you to configure the shape of the torrent array.
  49.  
  50. 1. Linear Torrent Array
  51.  
  52. This is the default setup of the configuration in the Torrents library. If
  53. (this.targetAsCenter) is true, the location of the first torrent is twice the
  54. distance between the caster and the target ground, else, the location is exactly
  55. the target ground.
  56.  
  57. Conditions:
  58.  
  59. - (this.torrentCountBase + this.torrentCountPerLevel*level) > 1
  60. - (this.torrentDistanceBase + this.torrentDistancePerLevel*level) != 0.00
  61. - (this.angleDeclinationBase + this.angleDeclinationPerLevel*level) == 0.00
  62.  
  63. 2. Circular Torrent Array
  64.  
  65. If (this.targetAsCenter) is true, the center of the circle is the target ground,
  66. else, the caster's position.
  67.  
  68. Conditions:
  69.  
  70. - (this.torrentCountBase + this.torrentCountPerLevel*level) > 1
  71. - (this.torrentDistanceBase + this.torrentDistancePerLevel*level) == 0.00
  72. - (this.angleDeclinationBase + this.angleDeclinationPerLevel*level) ==
  73. 360.00/(this.torrentCountBase + this.torrentCountPerLevel*level)
  74.  
  75. 3. Spiral Torrent Array
  76.  
  77. If (this.targetAsCenter) is true, the center of the spiral is the target ground,
  78. else, the caster's position.
  79.  
  80. Conditions:
  81.  
  82. - (this.torrentCountBase + this.torrentCountPerLevel*level) > 1
  83. - (this.torrentDistanceBase + this.torrentDistancePerLevel*level) != 0.00
  84. - (this.angleDeclinationBase + this.angleDeclinationPerLevel*level) != 0.00
  85.  
  86.  
  87. |-------------------|
  88. | Configuration API |
  89. |-------------------|
  90.  
  91. //! textmacro TORRENT_ARRAY_CONFIGURATION("SPELL_ID")
  92. - Marks the start of a new configuration set for a new type of
  93. TorrentArray spell
  94. - Input the activation spell's rawcode as
  95. the argument (Omit the '' delimiters)
  96.  
  97. //! textmacro END_TORRENT_ARRAY_CONFIGURATION()
  98. - Marks the end of a configuration set
  99.  
  100. this.pauseTossedTargets
  101. - Determines if the tossed units are paused or not (Normally, you
  102. should set this to true)
  103.  
  104. this.tossTargets
  105. - Determines if the toss unit feature is enabled or not
  106.  
  107. this.blindEnemies
  108. - Determines if the torrent borders will be hidden from the
  109. enemies' vision
  110.  
  111. this.targetAsCenter
  112. - If true, the target ground's location will serve as the basis
  113. for where the location of the first torrent will deviate from
  114. but if false, the caster's location will serve as the basis
  115. of deviation instead. This might be good to enable if you're
  116. configuring a circular of a spiral array of torrents so that
  117. it will have its center/origin at the target location instead
  118. of the caster's.
  119.  
  120. this.torrentCountBase
  121. this.torrentCountPerLevel
  122. - Determines the torrent count
  123.  
  124. this.timerDelayBase
  125. this.timerDelayPerLevel
  126. - Determines the delay of the first torrent's explosion after
  127. its appearance
  128.  
  129. this.releaseIntervalBase
  130. this.releaseIntervalPerLevel
  131. - Determines the time interval of the next torrent release
  132.  
  133. this.torrentDistanceBase
  134. this.torrentDistancePerLevel
  135. - Determines the distance between the torrents
  136.  
  137. this.angleDeclinationBase
  138. this.angleDeclinationPerLevel
  139. - Determines the angle declination of the torrents' location
  140. with respect to the caster as the origin
  141.  
  142. this.durationBase
  143. this.durationPerLevel
  144. - Determines the duration of the torrent
  145.  
  146. this.torrentRadiusBase
  147. this.torrentRadiusPerLevel
  148. - Determines the radius area affected by torrent
  149.  
  150. this.initialDamageBase
  151. this.initialDamagePerLevel
  152. - Determines the damage done by the torrent upon its appearance
  153.  
  154. this.damagePerSecondBase
  155. this.damagePerSecondPerLevel
  156. - Determines the damage dealt per second to the affected units
  157.  
  158. this.torrentHeightBase
  159. this.torrentHeightPerLevel
  160. - Determines the maximum height of the thrown units
  161.  
  162. this.borderDistance
  163. - Determines the distance of the border special effect from
  164. each other
  165.  
  166. this.attackType
  167. - Determines the attack type of the damage by the torrent
  168.  
  169. this.damageType
  170. - Determines the damage type of the damage by the torrent
  171.  
  172. this.weaponType
  173. - Determines the weapon type of the damage by the torrent
  174.  
  175. this.selfFilter
  176. this.allyFilter
  177. this.structureFilter
  178. this.mechanicalFilter
  179. this.magicImmuneFilter
  180. this.etherealFilter
  181. this.illusionFilter
  182. this.deadFilter
  183. - The following booleans determines the type of units allowed
  184. as the spell's target
  185.  
  186. this.onTorrentSummonSfxModel
  187. - Determines the model of the SFX when a torrent is set up
  188.  
  189. this.torrentSfxModel
  190. - Determines the SFXModel used for the torrent
  191.  
  192. this.borderSfxModel
  193. - Determines the SFXModel used for the spell borders
  194.  
  195. this.tossedTargetSfxModel
  196. - Determines the SFXModel used to attach to the tossed targets
  197.  
  198. this.landedTargetSfxModel
  199. - Determines the SFXModel used to attach to the affected units
  200. upon landing
  201.  
  202. this.tossedTargetSfxAttachPoint
  203. - Determines the attachment point for tossedTargetSfxModel
  204.  
  205. this.landedTargetSfxAttachPoint
  206. - Determines the attachment point for landedTargetSfxModel
  207.  
  208. this.tossedTargetAnimation
  209. - Determines the animation played by the affected units when
  210. being thrown on air (Default value is an empty string)
  211.  
  212. this.torrentExplosionHandler
  213. - The boolexpr of the code that will run upon each torrent's
  214. explosion
  215.  
  216. this.torrentVanishHandler
  217. - The boolexpr of the code that will run when each torrent
  218. vanishes
  219.  
  220.  
  221. |-------|
  222. | Other |
  223. |-------|
  224.  
  225. Inside the torrentExplosionHandler function and torrentVanishHandler function,
  226. you can use the following variables:
  227.  
  228. static TorrentArray triggerInstance
  229. - Use this to refer to the TorrentArray instance that the exploding or
  230. vanishing Torrent belongs
  231.  
  232. integer level
  233. - Use this to refer to the level of a TorrentArray instance
  234. - You might want to use this in conjunction with TorrentArray.triggerInstance
  235. (i.e. TorrentArray.triggerInstance.level) so you can refer to its stats
  236. like radius, initialDamage, etc. Just do not change their values.
  237.  
  238.  
  239. *===============================================================================================*/
  240.  
  241.  
  242. private struct TorrentList extends array
  243.  
  244. Torrent torrentNode
  245.  
  246. implement LinkedList
  247.  
  248. endstruct
  249.  
  250. struct TorrentArray extends array
  251.  
  252. private static Table table
  253. private static thistype configurationCount = 0
  254. private thistype configurationId
  255. private TorrentList current
  256. private TorrentList list
  257. private BoolExpr torrentExplosionHandlerExpr
  258. private BoolExpr torrentVanishHandlerExpr
  259. private string onSummonSfxModelString
  260. private string torrentSfxModelString
  261. private string borderSfxModelString
  262. private string tossedTargetSfxModelString
  263. private string landedTargetSfxModelString
  264. readonly static thistype triggerInstance = 0
  265. readonly integer level
  266. boolean pauseTossedTargets
  267. boolean tossTargets
  268. boolean blindEnemies
  269. boolean targetAsCenter
  270. integer torrentCountBase
  271. integer torrentCountPerLevel
  272. real timerDelayBase
  273. real timerDelayPerLevel
  274. real releaseIntervalBase
  275. real releaseIntervalPerLevel
  276. real torrentDistanceBase
  277. real torrentDistancePerLevel
  278. real angleDeclinationBase
  279. real angleDeclinationPerLevel
  280. real durationBase
  281. real durationPerLevel
  282. real torrentRadiusBase
  283. real torrentRadiusPerLevel
  284. real initialDamageBase
  285. real initialDamagePerLevel
  286. real damagePerSecondBase
  287. real damagePerSecondPerLevel
  288. real torrentHeightBase
  289. real torrentHeightPerLevel
  290. real borderDistance
  291. attacktype attackType
  292. damagetype damageType
  293. weapontype weaponType
  294. boolean selfFilter
  295. boolean allyFilter
  296. boolean structureFilter
  297. boolean mechanicalFilter
  298. boolean magicImmuneFilter
  299. boolean etherealFilter
  300. boolean illusionFilter
  301. boolean deadFilter
  302. string tossedTargetSfxAttachPoint
  303. string landedTargetSfxAttachPoint
  304. string tossedTargetAnimation
  305.  
  306. implement Alloc
  307.  
  308. private static method periodic takes nothing returns nothing
  309. local Timer expired = Timer.expired
  310. local thistype this = expired.data
  311. local TorrentList current = .current
  312. set triggerInstance = this
  313. call current.torrentNode.explode(.configurationId.tossTargets)
  314. set triggerInstance = 0
  315. if current.next == 0 then
  316. /* If the last Torrent in the list has exploded, destroy
  317. this spell instance. */
  318. call expired.free()
  319. call .list.destroy()
  320. call .deallocate()
  321. else
  322. set .current = current.next
  323. endif
  324. endmethod
  325.  
  326. private static method onDelay takes nothing returns nothing
  327. local Timer expired = Timer.expired
  328. local thistype this = expired.data
  329. local thistype id = .configurationId
  330. call expired.start(id.releaseIntervalBase + id.releaseIntervalPerLevel*.level, true, function thistype.periodic)
  331. endmethod
  332.  
  333. /* After casting, determine the ability casted and then get
  334. its configuration id */
  335. private static method onCast takes nothing returns nothing
  336. local thistype this = allocate()
  337. local integer spellId = Spell.abilityId()
  338. local thistype id = table[spellId]
  339. local real casterX = GetUnitX(Spell.caster())
  340. local real casterY = GetUnitY(Spell.caster())
  341. local real dx = Spell.targetX() - casterX
  342. local real dy = Spell.targetY() - casterY
  343. local real dr = SquareRoot(dx*dx + dy*dy)
  344. local integer count = id.torrentCountBase + id.torrentCountPerLevel*Spell.level()
  345. local real radius = id.torrentRadiusBase + id.torrentRadiusPerLevel*Spell.level()
  346. local real torrentHeight = id.torrentHeightBase + id.torrentHeightPerLevel*Spell.level()
  347. local real initialDamage = id.initialDamageBase + id.initialDamagePerLevel*Spell.level()
  348. local real damagePerSecond = id.damagePerSecondBase + id.damagePerSecondPerLevel*Spell.level()
  349. local real tordistance = id.torrentDistanceBase + id.torrentDistancePerLevel*Spell.level()
  350. local real angledec = id.angleDeclinationBase + id.angleDeclinationPerLevel*Spell.level()
  351. local real duration = id.durationBase + id.durationPerLevel*Spell.level()
  352. local attacktype attackType = id.attackType
  353. local damagetype damageType = id.damageType
  354. local weapontype weaponType = id.weaponType
  355. local boolean selfFilter = id.selfFilter
  356. local boolean allyFilter = id.allyFilter
  357. local boolean structureFilter = id.structureFilter
  358. local boolean mechanicalFilter = id.mechanicalFilter
  359. local boolean magicImmuneFilter = id.magicImmuneFilter
  360. local boolean etherealFilter = id.etherealFilter
  361. local boolean illusionFilter = id.illusionFilter
  362. local boolean deadFilter = id.deadFilter
  363. local boolean pauseTossedTargets = id.pauseTossedTargets
  364. local string onSummonSfxModel = id.onSummonSfxModelString
  365. local string borderModel = id.borderSfxModelString
  366. local string torrentModel = id.torrentSfxModelString
  367. local string staticSfxModel = id.tossedTargetSfxModelString
  368. local string targetSfxModel = id.landedTargetSfxModelString
  369. local string staticSfxAttachPoint = id.tossedTargetSfxAttachPoint
  370. local string targetSfxAttachPoint = id.landedTargetSfxAttachPoint
  371. local string targetAnimation = id.tossedTargetAnimation
  372. local BoolExpr onExplode = id.torrentExplosionHandlerExpr
  373. local BoolExpr onVanish = id.torrentVanishHandlerExpr
  374. local integer borders = R2I(2*radius*bj_PI/id.borderDistance)
  375. local real arcTan = Atan2(dy, dx)
  376. local TorrentList list = TorrentList.create()
  377. local real angle = 0
  378. local real distance
  379. local real centerX
  380. local real centerY
  381. local real x
  382. local real y
  383. local integer i
  384. local Torrent torrent
  385. local TorrentList node
  386. /* Exit immediately if the torrent count is lessthan 1 */
  387. if count <= 0 then
  388. return
  389. endif
  390. set .configurationId = id
  391. set .level = level
  392. set .list = list
  393. if id.blindEnemies and IsUnitEnemy(Spell.caster(), GetLocalPlayer()) then
  394. /* Hide the torrent borders from enemies' vision */
  395. set borderModel = ""
  396. endif
  397. /* Setup torrents in their designated location */
  398. loop
  399. exitwhen count == 0
  400. set count = count - 1
  401. set angle = arcTan + bj_DEGTORAD*(angledec*count)
  402. set distance = dr + tordistance*count
  403. if id.targetAsCenter then
  404. set centerX = Spell.targetX() + distance*Cos(angle)
  405. set centerY = Spell.targetY() + distance*Sin(angle)
  406. else
  407. set centerX = casterX + distance*Cos(angle)
  408. set centerY = casterY + distance*Sin(angle)
  409. endif
  410. /* Implement map bounds */
  411. if centerX < WorldBounds.minX then
  412. set centerX = WorldBounds.minX
  413. elseif centerX > WorldBounds.maxX then
  414. set centerX = WorldBounds.maxX
  415. endif
  416. if centerY < WorldBounds.minY then
  417. set centerY = WorldBounds.minY
  418. elseif centerY > WorldBounds.maxY then
  419. set centerY = WorldBounds.maxY
  420. endif
  421. /* Create the torrent and setup the neccessary data */
  422. set torrent = Torrent.create(centerX, centerY, radius, borders, torrentModel, borderModel, onSummonSfxModel)
  423. set torrent.caster = Spell.caster()
  424. set torrent.explosionDamage = initialDamage
  425. set torrent.damagePerSecond = damagePerSecond
  426. set torrent.height = torrentHeight
  427. set torrent.duration = duration
  428. set torrent.attackType = attackType
  429. set torrent.damageType = damageType
  430. set torrent.weaponType = weaponType
  431. set torrent.selfFilter = selfFilter
  432. set torrent.allyFilter = allyFilter
  433. set torrent.structureFilter = structureFilter
  434. set torrent.mechanicalFilter = mechanicalFilter
  435. set torrent.magicImmuneFilter = magicImmuneFilter
  436. set torrent.etherealFilter = etherealFilter
  437. set torrent.illusionFilter = illusionFilter
  438. set torrent.deadFilter = deadFilter
  439. set torrent.pauseTargets = pauseTossedTargets
  440. set torrent.tossedTargetSfxModel = staticSfxModel
  441. set torrent.landedTargetSfxModel = targetSfxModel
  442. set torrent.tossedTargetSfxAttachPoint = staticSfxAttachPoint
  443. set torrent.landedTargetSfxAttachPoint = targetSfxAttachPoint
  444. set torrent.tossedTargetAnimation = targetAnimation
  445. call torrent.onTorrentExplode(onExplode)
  446. call torrent.onTorrentVanish(onVanish)
  447. set node = TorrentList.allocate()
  448. set node.torrentNode = torrent
  449. call list.insertNode(node)
  450. endloop
  451. set .current = list.next
  452. call Timer.newEx(this).start((id.timerDelayBase + id.timerDelayPerLevel*level) - (id.releaseIntervalBase + id.releaseIntervalPerLevel*level), false, function thistype.onDelay)
  453. endmethod
  454.  
  455. method operator onTorrentSummonSfxModel= takes string model returns nothing
  456. set onSummonSfxModelString = model
  457. call PreloadEffect(model)
  458. endmethod
  459.  
  460. method operator torrentSfxModel= takes string model returns nothing
  461. set torrentSfxModelString = model
  462. call PreloadEffect(model)
  463. endmethod
  464.  
  465. method operator borderSfxModel= takes string model returns nothing
  466. set borderSfxModelString = model
  467. call PreloadEffect(model)
  468. endmethod
  469.  
  470. method operator tossedTargetSfxModel= takes string model returns nothing
  471. set tossedTargetSfxModelString = model
  472. call PreloadEffect(model)
  473. endmethod
  474.  
  475. method operator landedTargetSfxModel= takes string model returns nothing
  476. set landedTargetSfxModelString = model
  477. call PreloadEffect(model)
  478. endmethod
  479.  
  480. method operator torrentExplosionHandler= takes code handlerFunction returns nothing
  481. set torrentExplosionHandlerExpr = BoolExpr[handlerFunction]
  482. return
  483. endmethod
  484.  
  485. method operator torrentVanishHandler= takes code handlerFunction returns nothing
  486. set torrentVanishHandlerExpr = BoolExpr[handlerFunction]
  487. return
  488. endmethod
  489.  
  490. debug private static method debugDelayed takes nothing returns nothing
  491. debug local Timer expired = Timer.expired
  492. debug call debug("|CFFFF0000ERROR: Attempt to double-register the activation ability '" + I2S(expired.data) + "'|R")
  493. debug call expired.free()
  494. debug endmethod
  495.  
  496. static method new takes integer spellId returns thistype
  497. debug if table.has(spellId) then
  498. debug call Timer.newEx(spellId).start(0.00, false, function thistype.debugDelayed)
  499. debug return 0
  500. debug endif
  501. set configurationCount = configurationCount + 1
  502. set table[spellId] = configurationCount
  503. call RegisterSpellEffectEvent(spellId, function thistype.onCast)
  504. return configurationCount
  505. endmethod
  506.  
  507. private static method init takes nothing returns nothing
  508. set table = Table.create()
  509. endmethod
  510.  
  511. implement Initializer
  512.  
  513. endstruct
  514.  
  515. //! textmacro TORRENT_ARRAY_CONFIGURATION takes SPELL_ID
  516. struct TorrentArray_ConfigurationId_$SPELL_ID$ extends array
  517. private static method onInit takes nothing returns nothing
  518. local TorrentArray this = TorrentArray.new('$SPELL_ID$')
  519. //! endtextmacro
  520.  
  521. //! textmacro END_TORRENT_ARRAY_CONFIGURATION
  522. endmethod
  523. endstruct
  524. //! endtextmacro
  525.  
  526.  
  527. endlibrary
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement