Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- library TorrentArray /*
- */requires /*
- */TorrentSystem /*
- */SpellEffectEvent /*
- */SpellEffectUtils /*
- */Alloc /*
- */Timer /*
- */Table /*
- */LinkedList /*
- */BooleanExpression /*
- */ResourcePreloader /*
- */MapBounds /*
- */Initializer /*
- |---------|
- | Credits |
- |---------|
- Author:
- - AGD
- Dependencies:
- - Bribe (SpellEffectEvent, Table)
- - Vexorian (TimerUtils)
- - Nestharus (WorldBounds)
- - AGD (Torrent, ResourcePreloader)
- |-----------|
- | Importing |
- |-----------|
- - Import the dummy.mdx model to your map
- - Copy the dummy unit and the Torrent ability in Object Editor
- - Copy the trigger category containing this script and its dependencies
- - Configure the spell's data in the default configuration library or alternatively,
- make your own one
- |---------------------|
- | Configuration Hints |
- |---------------------|
- The configuration allows you to do many possible tricks. One of these is the trick
- that allows you to configure the shape of the torrent array.
- 1. Linear Torrent Array
- This is the default setup of the configuration in the Torrents library. If
- (this.targetAsCenter) is true, the location of the first torrent is twice the
- distance between the caster and the target ground, else, the location is exactly
- the target ground.
- Conditions:
- - (this.torrentCountBase + this.torrentCountPerLevel*level) > 1
- - (this.torrentDistanceBase + this.torrentDistancePerLevel*level) != 0.00
- - (this.angleDeclinationBase + this.angleDeclinationPerLevel*level) == 0.00
- 2. Circular Torrent Array
- If (this.targetAsCenter) is true, the center of the circle is the target ground,
- else, the caster's position.
- Conditions:
- - (this.torrentCountBase + this.torrentCountPerLevel*level) > 1
- - (this.torrentDistanceBase + this.torrentDistancePerLevel*level) == 0.00
- - (this.angleDeclinationBase + this.angleDeclinationPerLevel*level) ==
- 360.00/(this.torrentCountBase + this.torrentCountPerLevel*level)
- 3. Spiral Torrent Array
- If (this.targetAsCenter) is true, the center of the spiral is the target ground,
- else, the caster's position.
- Conditions:
- - (this.torrentCountBase + this.torrentCountPerLevel*level) > 1
- - (this.torrentDistanceBase + this.torrentDistancePerLevel*level) != 0.00
- - (this.angleDeclinationBase + this.angleDeclinationPerLevel*level) != 0.00
- |-------------------|
- | Configuration API |
- |-------------------|
- //! textmacro TORRENT_ARRAY_CONFIGURATION("SPELL_ID")
- - Marks the start of a new configuration set for a new type of
- TorrentArray spell
- - Input the activation spell's rawcode as
- the argument (Omit the '' delimiters)
- //! textmacro END_TORRENT_ARRAY_CONFIGURATION()
- - Marks the end of a configuration set
- this.pauseTossedTargets
- - Determines if the tossed units are paused or not (Normally, you
- should set this to true)
- this.tossTargets
- - Determines if the toss unit feature is enabled or not
- this.blindEnemies
- - Determines if the torrent borders will be hidden from the
- enemies' vision
- this.targetAsCenter
- - If true, the target ground's location will serve as the basis
- for where the location of the first torrent will deviate from
- but if false, the caster's location will serve as the basis
- of deviation instead. This might be good to enable if you're
- configuring a circular of a spiral array of torrents so that
- it will have its center/origin at the target location instead
- of the caster's.
- this.torrentCountBase
- this.torrentCountPerLevel
- - Determines the torrent count
- this.timerDelayBase
- this.timerDelayPerLevel
- - Determines the delay of the first torrent's explosion after
- its appearance
- this.releaseIntervalBase
- this.releaseIntervalPerLevel
- - Determines the time interval of the next torrent release
- this.torrentDistanceBase
- this.torrentDistancePerLevel
- - Determines the distance between the torrents
- this.angleDeclinationBase
- this.angleDeclinationPerLevel
- - Determines the angle declination of the torrents' location
- with respect to the caster as the origin
- this.durationBase
- this.durationPerLevel
- - Determines the duration of the torrent
- this.torrentRadiusBase
- this.torrentRadiusPerLevel
- - Determines the radius area affected by torrent
- this.initialDamageBase
- this.initialDamagePerLevel
- - Determines the damage done by the torrent upon its appearance
- this.damagePerSecondBase
- this.damagePerSecondPerLevel
- - Determines the damage dealt per second to the affected units
- this.torrentHeightBase
- this.torrentHeightPerLevel
- - Determines the maximum height of the thrown units
- this.borderDistance
- - Determines the distance of the border special effect from
- each other
- this.attackType
- - Determines the attack type of the damage by the torrent
- this.damageType
- - Determines the damage type of the damage by the torrent
- this.weaponType
- - Determines the weapon type of the damage by the torrent
- this.selfFilter
- this.allyFilter
- this.structureFilter
- this.mechanicalFilter
- this.magicImmuneFilter
- this.etherealFilter
- this.illusionFilter
- this.deadFilter
- - The following booleans determines the type of units allowed
- as the spell's target
- this.onTorrentSummonSfxModel
- - Determines the model of the SFX when a torrent is set up
- this.torrentSfxModel
- - Determines the SFXModel used for the torrent
- this.borderSfxModel
- - Determines the SFXModel used for the spell borders
- this.tossedTargetSfxModel
- - Determines the SFXModel used to attach to the tossed targets
- this.landedTargetSfxModel
- - Determines the SFXModel used to attach to the affected units
- upon landing
- this.tossedTargetSfxAttachPoint
- - Determines the attachment point for tossedTargetSfxModel
- this.landedTargetSfxAttachPoint
- - Determines the attachment point for landedTargetSfxModel
- this.tossedTargetAnimation
- - Determines the animation played by the affected units when
- being thrown on air (Default value is an empty string)
- this.torrentExplosionHandler
- - The boolexpr of the code that will run upon each torrent's
- explosion
- this.torrentVanishHandler
- - The boolexpr of the code that will run when each torrent
- vanishes
- |-------|
- | Other |
- |-------|
- Inside the torrentExplosionHandler function and torrentVanishHandler function,
- you can use the following variables:
- static TorrentArray triggerInstance
- - Use this to refer to the TorrentArray instance that the exploding or
- vanishing Torrent belongs
- integer level
- - Use this to refer to the level of a TorrentArray instance
- - You might want to use this in conjunction with TorrentArray.triggerInstance
- (i.e. TorrentArray.triggerInstance.level) so you can refer to its stats
- like radius, initialDamage, etc. Just do not change their values.
- *===============================================================================================*/
- private struct TorrentList extends array
- Torrent torrentNode
- implement LinkedList
- endstruct
- struct TorrentArray extends array
- private static Table table
- private static thistype configurationCount = 0
- private thistype configurationId
- private TorrentList current
- private TorrentList list
- private BoolExpr torrentExplosionHandlerExpr
- private BoolExpr torrentVanishHandlerExpr
- private string onSummonSfxModelString
- private string torrentSfxModelString
- private string borderSfxModelString
- private string tossedTargetSfxModelString
- private string landedTargetSfxModelString
- readonly static thistype triggerInstance = 0
- readonly integer level
- boolean pauseTossedTargets
- boolean tossTargets
- boolean blindEnemies
- boolean targetAsCenter
- integer torrentCountBase
- integer torrentCountPerLevel
- real timerDelayBase
- real timerDelayPerLevel
- real releaseIntervalBase
- real releaseIntervalPerLevel
- real torrentDistanceBase
- real torrentDistancePerLevel
- real angleDeclinationBase
- real angleDeclinationPerLevel
- real durationBase
- real durationPerLevel
- real torrentRadiusBase
- real torrentRadiusPerLevel
- real initialDamageBase
- real initialDamagePerLevel
- real damagePerSecondBase
- real damagePerSecondPerLevel
- real torrentHeightBase
- real torrentHeightPerLevel
- real borderDistance
- attacktype attackType
- damagetype damageType
- weapontype weaponType
- boolean selfFilter
- boolean allyFilter
- boolean structureFilter
- boolean mechanicalFilter
- boolean magicImmuneFilter
- boolean etherealFilter
- boolean illusionFilter
- boolean deadFilter
- string tossedTargetSfxAttachPoint
- string landedTargetSfxAttachPoint
- string tossedTargetAnimation
- implement Alloc
- private static method periodic takes nothing returns nothing
- local Timer expired = Timer.expired
- local thistype this = expired.data
- local TorrentList current = .current
- set triggerInstance = this
- call current.torrentNode.explode(.configurationId.tossTargets)
- set triggerInstance = 0
- if current.next == 0 then
- /* If the last Torrent in the list has exploded, destroy
- this spell instance. */
- call expired.free()
- call .list.destroy()
- call .deallocate()
- else
- set .current = current.next
- endif
- endmethod
- private static method onDelay takes nothing returns nothing
- local Timer expired = Timer.expired
- local thistype this = expired.data
- local thistype id = .configurationId
- call expired.start(id.releaseIntervalBase + id.releaseIntervalPerLevel*.level, true, function thistype.periodic)
- endmethod
- /* After casting, determine the ability casted and then get
- its configuration id */
- private static method onCast takes nothing returns nothing
- local thistype this = allocate()
- local integer spellId = Spell.abilityId()
- local thistype id = table[spellId]
- local real casterX = GetUnitX(Spell.caster())
- local real casterY = GetUnitY(Spell.caster())
- local real dx = Spell.targetX() - casterX
- local real dy = Spell.targetY() - casterY
- local real dr = SquareRoot(dx*dx + dy*dy)
- local integer count = id.torrentCountBase + id.torrentCountPerLevel*Spell.level()
- local real radius = id.torrentRadiusBase + id.torrentRadiusPerLevel*Spell.level()
- local real torrentHeight = id.torrentHeightBase + id.torrentHeightPerLevel*Spell.level()
- local real initialDamage = id.initialDamageBase + id.initialDamagePerLevel*Spell.level()
- local real damagePerSecond = id.damagePerSecondBase + id.damagePerSecondPerLevel*Spell.level()
- local real tordistance = id.torrentDistanceBase + id.torrentDistancePerLevel*Spell.level()
- local real angledec = id.angleDeclinationBase + id.angleDeclinationPerLevel*Spell.level()
- local real duration = id.durationBase + id.durationPerLevel*Spell.level()
- local attacktype attackType = id.attackType
- local damagetype damageType = id.damageType
- local weapontype weaponType = id.weaponType
- local boolean selfFilter = id.selfFilter
- local boolean allyFilter = id.allyFilter
- local boolean structureFilter = id.structureFilter
- local boolean mechanicalFilter = id.mechanicalFilter
- local boolean magicImmuneFilter = id.magicImmuneFilter
- local boolean etherealFilter = id.etherealFilter
- local boolean illusionFilter = id.illusionFilter
- local boolean deadFilter = id.deadFilter
- local boolean pauseTossedTargets = id.pauseTossedTargets
- local string onSummonSfxModel = id.onSummonSfxModelString
- local string borderModel = id.borderSfxModelString
- local string torrentModel = id.torrentSfxModelString
- local string staticSfxModel = id.tossedTargetSfxModelString
- local string targetSfxModel = id.landedTargetSfxModelString
- local string staticSfxAttachPoint = id.tossedTargetSfxAttachPoint
- local string targetSfxAttachPoint = id.landedTargetSfxAttachPoint
- local string targetAnimation = id.tossedTargetAnimation
- local BoolExpr onExplode = id.torrentExplosionHandlerExpr
- local BoolExpr onVanish = id.torrentVanishHandlerExpr
- local integer borders = R2I(2*radius*bj_PI/id.borderDistance)
- local real arcTan = Atan2(dy, dx)
- local TorrentList list = TorrentList.create()
- local real angle = 0
- local real distance
- local real centerX
- local real centerY
- local real x
- local real y
- local integer i
- local Torrent torrent
- local TorrentList node
- /* Exit immediately if the torrent count is lessthan 1 */
- if count <= 0 then
- return
- endif
- set .configurationId = id
- set .level = level
- set .list = list
- if id.blindEnemies and IsUnitEnemy(Spell.caster(), GetLocalPlayer()) then
- /* Hide the torrent borders from enemies' vision */
- set borderModel = ""
- endif
- /* Setup torrents in their designated location */
- loop
- exitwhen count == 0
- set count = count - 1
- set angle = arcTan + bj_DEGTORAD*(angledec*count)
- set distance = dr + tordistance*count
- if id.targetAsCenter then
- set centerX = Spell.targetX() + distance*Cos(angle)
- set centerY = Spell.targetY() + distance*Sin(angle)
- else
- set centerX = casterX + distance*Cos(angle)
- set centerY = casterY + distance*Sin(angle)
- endif
- /* Implement map bounds */
- if centerX < WorldBounds.minX then
- set centerX = WorldBounds.minX
- elseif centerX > WorldBounds.maxX then
- set centerX = WorldBounds.maxX
- endif
- if centerY < WorldBounds.minY then
- set centerY = WorldBounds.minY
- elseif centerY > WorldBounds.maxY then
- set centerY = WorldBounds.maxY
- endif
- /* Create the torrent and setup the neccessary data */
- set torrent = Torrent.create(centerX, centerY, radius, borders, torrentModel, borderModel, onSummonSfxModel)
- set torrent.caster = Spell.caster()
- set torrent.explosionDamage = initialDamage
- set torrent.damagePerSecond = damagePerSecond
- set torrent.height = torrentHeight
- set torrent.duration = duration
- set torrent.attackType = attackType
- set torrent.damageType = damageType
- set torrent.weaponType = weaponType
- set torrent.selfFilter = selfFilter
- set torrent.allyFilter = allyFilter
- set torrent.structureFilter = structureFilter
- set torrent.mechanicalFilter = mechanicalFilter
- set torrent.magicImmuneFilter = magicImmuneFilter
- set torrent.etherealFilter = etherealFilter
- set torrent.illusionFilter = illusionFilter
- set torrent.deadFilter = deadFilter
- set torrent.pauseTargets = pauseTossedTargets
- set torrent.tossedTargetSfxModel = staticSfxModel
- set torrent.landedTargetSfxModel = targetSfxModel
- set torrent.tossedTargetSfxAttachPoint = staticSfxAttachPoint
- set torrent.landedTargetSfxAttachPoint = targetSfxAttachPoint
- set torrent.tossedTargetAnimation = targetAnimation
- call torrent.onTorrentExplode(onExplode)
- call torrent.onTorrentVanish(onVanish)
- set node = TorrentList.allocate()
- set node.torrentNode = torrent
- call list.insertNode(node)
- endloop
- set .current = list.next
- call Timer.newEx(this).start((id.timerDelayBase + id.timerDelayPerLevel*level) - (id.releaseIntervalBase + id.releaseIntervalPerLevel*level), false, function thistype.onDelay)
- endmethod
- method operator onTorrentSummonSfxModel= takes string model returns nothing
- set onSummonSfxModelString = model
- call PreloadEffect(model)
- endmethod
- method operator torrentSfxModel= takes string model returns nothing
- set torrentSfxModelString = model
- call PreloadEffect(model)
- endmethod
- method operator borderSfxModel= takes string model returns nothing
- set borderSfxModelString = model
- call PreloadEffect(model)
- endmethod
- method operator tossedTargetSfxModel= takes string model returns nothing
- set tossedTargetSfxModelString = model
- call PreloadEffect(model)
- endmethod
- method operator landedTargetSfxModel= takes string model returns nothing
- set landedTargetSfxModelString = model
- call PreloadEffect(model)
- endmethod
- method operator torrentExplosionHandler= takes code handlerFunction returns nothing
- set torrentExplosionHandlerExpr = BoolExpr[handlerFunction]
- return
- endmethod
- method operator torrentVanishHandler= takes code handlerFunction returns nothing
- set torrentVanishHandlerExpr = BoolExpr[handlerFunction]
- return
- endmethod
- debug private static method debugDelayed takes nothing returns nothing
- debug local Timer expired = Timer.expired
- debug call debug("|CFFFF0000ERROR: Attempt to double-register the activation ability '" + I2S(expired.data) + "'|R")
- debug call expired.free()
- debug endmethod
- static method new takes integer spellId returns thistype
- debug if table.has(spellId) then
- debug call Timer.newEx(spellId).start(0.00, false, function thistype.debugDelayed)
- debug return 0
- debug endif
- set configurationCount = configurationCount + 1
- set table[spellId] = configurationCount
- call RegisterSpellEffectEvent(spellId, function thistype.onCast)
- return configurationCount
- endmethod
- private static method init takes nothing returns nothing
- set table = Table.create()
- endmethod
- implement Initializer
- endstruct
- //! textmacro TORRENT_ARRAY_CONFIGURATION takes SPELL_ID
- struct TorrentArray_ConfigurationId_$SPELL_ID$ extends array
- private static method onInit takes nothing returns nothing
- local TorrentArray this = TorrentArray.new('$SPELL_ID$')
- //! endtextmacro
- //! textmacro END_TORRENT_ARRAY_CONFIGURATION
- endmethod
- endstruct
- //! endtextmacro
- endlibrary
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement