Lightning
Version 1.01
Lightning is an end-point tracker and fader for lightning effects, built using T32. It is a highly efficient implementation.
Requirements:
- Jass NewGen
- T32
Updates:
- Version 1.01: Fixed Unit #2 terrain offset bug and added HEIGHT_OFFSET constant.
- Version 1.00: Release.
- Jass NewGen
- T32
JASS:
//
// _ ___ ___ _ _ _____ __ _ ___ __ _ ___
// | | |_ _|/ __| |_| |_ _| \| |_ _| \| |/ __|
// | |__ | || (_ | _ | | | | \ \ || || \ \ | (_ |
// |____|___|\___|_| |_| |_| |_|\__|___|_|\__|\___|
// By Lyncor. v1.01.
//
// What is Lightning?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Lightning is an efficient end-point tracker and fader for lightning
// effects in Warcraft III.
//
// How to implement?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Simply create a new trigger object called Lightning, go to 'Edit -> Convert
// to Custom Text', and replace everything that's there with this script.
//
// Lightning Codes (Thanks to Flare):
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// "CLPB" - Chain Lightning Primary
// "CLSB" - Chain Lightning Secondary
// "DRAB" - Drain
// "DRAL" - Drain Life
// "DRAM" - Drain mana
// "AFOD" - Finger of Death
// "FORK" - Forked Lightning
// "HWPB" - Healing Wave Primary
// "HWSB" - Healing Wave Secondary
// "CHIM" - Lightning Attack
// "LEAS" - Magic Leash
// "MBUR" - Mana Burn
// "MFPB" - Mana Flare
// "SPLK" - Spirit Link
//
// Functions:
// ¯¯¯¯¯¯¯¯¯¯¯¯
// For the creation functions:
// - "string code" is the lightning type as a string.
// - "real duration" is how long the lightning should last.
// - "boolean fade" is true if the lightning should fade over its duration.
//
// function Lightning_UnitUnit takes string code, unit from, unit to,
// real duration, boolean fade returns nothing
// - Creates and tracks lightning from one unit to another.
//
// function Lightning_CoordsUnit takes string code, real x, real y, real z,
// unit to, real duration, boolean fade returns nothing
// - Creates and tracks lightning from coordinates to a unit.
//
// function Lightning_UnitCoords takes string code, unit from,
// real x, real y, real z, real duration, boolean fade returns nothing
// - Creates and tracks lightning from a unit to coordinates.
//
// function Lightning_ColorLast takes real r, real g, real b returns nothing
// - Sets the colour of the last created lightning to the red,
// greed and blue values passed into the function (r, g, b).
// - The values are real numbers ranging from 0 to 1.
// - This must only be called immediately after calling a
// creation function.
//
// Thanks:
// ¯¯¯¯¯¯¯¯¯
// - Jesus4Lyf for assistance and writing T32.
//
library Lightning uses T32
globals
// This offset is applied for all unit lightning links.
private constant real HEIGHT_OFFSET=56.0
endglobals
//===========================================================
// DATA DECLARATION:
//
// The basic data for a link of lightning. This is so there
// is minimal array declaration, and faster recycling of unit
// handle ids.
//
private struct Link //extends array // JassHelper won't allow this with inheritance.
// Allocator that won't lose efficiency with inheritance.
// Faster than vJass allocator.
private static thistype array recycled
private static integer recycledMax=0
private static integer lastAlloc=0
static method alloc takes nothing returns thistype
if thistype.recycledMax==0 then
set thistype.lastAlloc=thistype.lastAlloc+1
return thistype(thistype.lastAlloc)
endif
set thistype.recycledMax=thistype.recycledMax-1
return thistype.recycled[thistype.recycledMax]
endmethod
method dealloc takes nothing returns nothing
set thistype.recycled[thistype.recycledMax]=this
set thistype.recycledMax=thistype.recycledMax+1
endmethod
// Data
lightning link
real x // Don't need 2 sets of these,
real y // because if it was linking coords
real z // to coords, it wouldn't move.
unit sU
unit eU
integer ticks
real r
real g
real b
real a
real aSlide
endstruct
//===========================================================
// CALLBACK DECLARATION:
//
// This is all the data and code segments used in the links'
// callback functions. Textmacros are brilliant, because they
// provide functional decomposition without any efficiency
// penalty.
//
// Globals have been used to shorten code (locals also have
// terribly ugly declarations) and provide an efficiency
// boost, as well as eliminate nulling concerns for the unit.
//
// T32 has been used to complete the razor sharp efficiency.
//
globals
private location LOC=Location(0,0)
endglobals
globals//locals
private real X1
private real Y1
private real Z1
private real X2
private real Y2
// Don't need Z2, can inline into the MoveLightning call.
private unit Unit
endglobals
//===========================================================
// Callback Snippets
//
//! textmacro LGHT_CB__LoadUnit1
set Unit=this.sU
set X1=GetUnitX(Unit)
set Y1=GetUnitY(Unit)
call MoveLocation(LOC,X1,Y1)
//! endtextmacro
//! textmacro LGHT_CB__LoadUnit2
set Unit=this.eU
set X2=GetUnitX(Unit)
set Y2=GetUnitY(Unit)
call MoveLocation(LOC,X2,Y2)
//! endtextmacro
//! textmacro LGHT_CB__EscapeClause
if this.ticks==0 then
call DestroyLightning(this.link)
call this.dealloc()
return true
endif
set this.ticks=this.ticks-1 // Is effectively at the end of the periodic function.
//! endtextmacro
//! textmacro LGHT_CB__AlphaUpkeep
call SetLightningColor(this.link,this.r,this.g,this.b,this.a)
set this.a=this.a-this.aSlide
//! endtextmacro
//===========================================================
// T32 Callbacks
//
// One for with alpha fading and one without for each cross
// of unit/coords. For free efficiency if you don't fade.
//
// Semantics:
// "U" means "Unit". "XY" means "Coordinates".
// "a" is for "alpha". Therefore:
// - UU means Unit to Unit, no alpha fade.
// - XYUa means Coordinates to Unit, with alpha fade.
// - etc.
//
private struct LinkUUa extends Link
private method periodic takes nothing returns boolean
//! runtextmacro LGHT_CB__EscapeClause()
//! runtextmacro LGHT_CB__LoadUnit1()
set Z1=GetLocationZ(LOC)+GetUnitFlyHeight(Unit)
//! runtextmacro LGHT_CB__LoadUnit2()
call MoveLightningEx(this.link,true,X1,Y1,Z1+HEIGHT_OFFSET,X2,Y2,GetLocationZ(LOC)+GetUnitFlyHeight(Unit)+HEIGHT_OFFSET)
//! runtextmacro LGHT_CB__AlphaUpkeep()
return false
endmethod
implement T32
endstruct
private struct LinkUU extends Link
private method periodic takes nothing returns boolean
//! runtextmacro LGHT_CB__EscapeClause()
//! runtextmacro LGHT_CB__LoadUnit1()
set Z1=GetLocationZ(LOC)+GetUnitFlyHeight(Unit)
//! runtextmacro LGHT_CB__LoadUnit2()
call MoveLightningEx(this.link,true,X1,Y1,Z1+HEIGHT_OFFSET,X2,Y2,GetLocationZ(LOC)+GetUnitFlyHeight(Unit)+HEIGHT_OFFSET)
return false
endmethod
implement T32
endstruct
private struct LinkXYUa extends Link
private method periodic takes nothing returns boolean
//! runtextmacro LGHT_CB__EscapeClause()
call MoveLocation(LOC,this.x,this.y)
set Z1=GetLocationZ(LOC)+this.z
//! runtextmacro LGHT_CB__LoadUnit2()
call MoveLightningEx(this.link,true,this.x,this.y,Z1,X2,Y2,GetLocationZ(LOC)+GetUnitFlyHeight(Unit)+HEIGHT_OFFSET)
//! runtextmacro LGHT_CB__AlphaUpkeep()
return false
endmethod
implement T32
endstruct
private struct LinkXYU extends Link
private method periodic takes nothing returns boolean
//! runtextmacro LGHT_CB__EscapeClause()
call MoveLocation(LOC,this.x,this.y)
set Z1=GetLocationZ(LOC)+this.z
//! runtextmacro LGHT_CB__LoadUnit2()
call MoveLightningEx(this.link,true,this.x,this.y,Z1,X2,Y2,GetLocationZ(LOC)+GetUnitFlyHeight(Unit)+HEIGHT_OFFSET)
return false
endmethod
implement T32
endstruct
private struct LinkUXYa extends Link
private method periodic takes nothing returns boolean
//! runtextmacro LGHT_CB__EscapeClause()
//! runtextmacro LGHT_CB__LoadUnit1()
set Z1=GetLocationZ(LOC)+GetUnitFlyHeight(Unit)
call MoveLocation(LOC,this.x,this.y)
call MoveLightningEx(this.link,true,X1,Y1,Z1+HEIGHT_OFFSET,this.x,this.y,GetLocationZ(LOC)+this.z)
//! runtextmacro LGHT_CB__AlphaUpkeep()
return false
endmethod
implement T32
endstruct
private struct LinkUXY extends Link
private method periodic takes nothing returns boolean
//! runtextmacro LGHT_CB__EscapeClause()
//! runtextmacro LGHT_CB__LoadUnit1()
set Z1=GetLocationZ(LOC)+GetUnitFlyHeight(Unit)
call MoveLocation(LOC,this.x,this.y)
call MoveLightningEx(this.link,true,X1,Y1,Z1+HEIGHT_OFFSET,this.x,this.y,GetLocationZ(LOC)+this.z)
return false
endmethod
implement T32
endstruct
//===========================================================
// PUBLIC INTERFACE:
//
// This is the declaration of all functionality exposed to
// end users. Once again, a global struct variable has been
// used to remove the ugly local declaration, and textmacros
// have been used for efficient functional decomposition.
//
globals//locals
private Link data
endglobals
//===========================================================
// Interface Snippets
//
//! textmacro LGHT_I__Unit1
set X1=GetUnitX(from)
set Y1=GetUnitY(from)
call MoveLocation(LOC,X1,Y1)
//! endtextmacro
//! textmacro LGHT_I__Unit2
set X2=GetUnitX(to)
set Y2=GetUnitY(to)
call MoveLocation(LOC,X2,Y2)
//! endtextmacro
//! textmacro LGHT_I__Start takes WHICH
set data.r=1.0
set data.g=1.0
set data.b=1.0
set data.ticks=R2I(duration/T32_PERIOD)
if fade then
set data.a=1.0
set data.aSlide=1/duration*T32_PERIOD
call Link$WHICH$a(data).startPeriodic()
else
call Link$WHICH$(data).startPeriodic()
endif
//! endtextmacro
//===========================================================
// Interface
//
public function UnitUnit takes string whichCode, unit from, unit to, real duration, boolean fade returns nothing
set data=Link.alloc()
set data.sU=from
set data.eU=to
//! runtextmacro LGHT_I__Unit1()
set Z1=GetLocationZ(LOC)+GetUnitFlyHeight(from)
//! runtextmacro LGHT_I__Unit2()
set data.link=AddLightningEx(whichCode,true,X1,Y1,Z1,X2,Y2,GetLocationZ(LOC)+GetUnitFlyHeight(to))
//! runtextmacro LGHT_I__Start("UU")
endfunction
public function CoordsUnit takes string whichCode, real x, real y, real z, unit to, real duration, boolean fade returns nothing
set data=Link.alloc()
set data.x=x
set data.y=y
set data.z=z
set data.eU=to
call MoveLocation(LOC,x,y)
set Z1=GetLocationZ(LOC)+z
//! runtextmacro LGHT_I__Unit2()
set data.link=AddLightningEx(whichCode,true,x,y,Z1,X2,Y2,GetLocationZ(LOC)+GetUnitFlyHeight(to))
//! runtextmacro LGHT_I__Start("XYU")
endfunction
public function UnitCoords takes string whichCode, unit from, real x, real y, real z, real duration, boolean fade returns nothing
set data=Link.alloc()
set data.sU=from
set data.x=x
set data.y=y
set data.z=z
//! runtextmacro LGHT_I__Unit1()
set Z1=GetLocationZ(LOC)+GetUnitFlyHeight(from)
call MoveLocation(LOC,x,y)
set data.link=AddLightningEx(whichCode,true,X1,Y1,Z1,x,y,GetLocationZ(LOC)+z)
//! runtextmacro LGHT_I__Start("UXY")
endfunction
// Let's not clutter our interfaces.
public function ColorLast takes real r, real g, real b returns nothing
set data.r=r
set data.g=g
set data.b=b
call SetLightningColor(data.link,r,g,b,1.0)
endfunction
//===========================================================
// Note to users:
//
// Keep smiling. God loves you. <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin :D" loading="lazy" data-shortname=":D" />
// Happy mapping.
endlibrary
Updates:
- Version 1.01: Fixed Unit #2 terrain offset bug and added HEIGHT_OFFSET constant.
- Version 1.00: Release.
ChainLightning
Version 1.00
ChainLightning is a flexible implementation of the Warcraft III spell, Chain Lightning. It allows for getting the damage type through Damage, specifying your own custom behavior on bounce, or changing the colour of the Lightning.
Requirements:
- Jass NewGen
- Lightning (see above)
- T32
- Recycle
- Damage
Updates:
- Version 1.00: Release.
- Jass NewGen
- Lightning (see above)
- T32
- Recycle
- Damage
JASS:
//
// ___ _ _ _ ___ __ _
// / __| |_| | /_\ |_ _| \| |
// | (__| _ |/ _ \ | || \ \ |
// \___|_| |_/_/_\_\___|_|\__|______ __ _ ___ __ _ ___
// | | |_ _|/ __| |_| |_ _| \| |_ _| \| |/ __|
// | |__ | || (_ | _ | | | | \ \ || || \ \ | (_ |
// |____|___|\___|_| |_| |_| |_|\__|___|_|\__|\___|
// By Lyncor. v1.00.
//
// What is ChainLightning?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// ChainLightning is a vJass implementation of the Warcraft III spell,
// Chain Lightning.
//
// Its colour and action on jump can both be customised.
//
// How to implement?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Simply create a new trigger object called ChainLightning, go to 'Edit ->
// Convert to Custom Text', and replace everything that's there with this script.
//
// Lightning Codes (Thanks to Flare):
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// "CLPB" - Chain Lightning Primary
// "CLSB" - Chain Lightning Secondary
// "DRAB" - Drain
// "DRAL" - Drain Life
// "DRAM" - Drain mana
// "AFOD" - Finger of Death
// "FORK" - Forked Lightning
// "HWPB" - Healing Wave Primary
// "HWSB" - Healing Wave Secondary
// "CHIM" - Lightning Attack
// "LEAS" - Magic Leash
// "MBUR" - Mana Burn
// "MFPB" - Mana Flare
// "SPLK" - Spirit Link
//
// Functions:
// ¯¯¯¯¯¯¯¯¯¯¯¯
// For the creation functions:
// - "string whichCode" is the lightning type as a string.
//
// function ChainLightning takes unit caster, unit source, unit target,
// string whichCode, real damage, integer hops returns nothing
// - Casts a simple damage chain lightning, dealing less damage each
// bounce.
// - The caster is the damage source (the unit dealing the damage).
// - The source is where the first hop comes from (usually the caster).
// - The target is where the first hop will land.
// - The damage is the damage on the first hop. After that, it will
// reduce by the hop damage factor on each hop - either the default
// or that explicitly set by using the SetLast function.
// function ChainLightning_SetLastHopDamageFactor takes real factor returns nothing
// - Use this to set the damage factor for the ChainLightning instance
// last created. Does not work with ChainLightningEx.
// - This must only be called immediately after calling ChainLightning.
//
// The following chunk relates to ChainLightningEx explicitly:
//
// function ChainLightningEx takes unit caster, unit source, string whichCode,
// ChainLightning_Callback onHop, boolean hitsEnemies, integer hops
// returns integer
// - Similar to above, but takes a ChainLightning_Callback which
// will be called on each hop, passing in the target.
// - "boolean hitsEnemies" is true for hitting enemies, and false for
// hitting allies (healing wave, etc).
// - The integer returned is an index for attaching data to. It will
// be between 1 and 8191, and will be passed into the onHop callback
// when it is called.
// function interface ChainLightning_Callback takes integer id, unit target
// returns nothing
// - This is for passing a callback into ChainLightningEx. The callback
// passed in will be called every hop.
// - "integer id" is the integer returned from the ChainLightningEx
// call.
// - "unit target" is the unit being hopped to.
// function ChainLightning_StartLastEx takes unit target returns nothing
// - To be called after ChainLightningEx, and after all data has been
// attached to be used in the callback.
// - Only call this once for each ChainLightningEx.
// - This is necessary for the first hop (which occurs immediately).
// Otherwise, it would not be possible to pass the data to the onHop
// callback.
// function ChainLightning_Sound takes unit target returns nothing
// - For use in your callback, if you wish to have the lightning sound.
//
// The following relates to either ChainLightning call:
//
// function ChainLightning_ColorLast takes real r, real g, real b returns nothing
// - Sets the colour of the last created chain lightning to the red,
// greed and blue values passed into the function (r, g, b).
// - The values are real numbers ranging from 0 to 1.
// - This must only be called immediately after calling ChainLightning
// or ChainLightning_StartLastEx.
//
// function ChainLightning_SetLastTimeBetweenHops takes real time returns nothing
// - This sets the time between hops.
// - This must only be called immediately after calling ChainLightning
// or ChainLightning_StartLastEx.
//
// function ChainLightning_SetlastMaxHopDistance takes real distance returns nothing
// - Sets the maximum distance a chain lightning instance will bounce
// to get a new target.
// - This must only be called immediately after calling ChainLightning
// or ChainLightning_StartLastEx.
//
// Thanks:
// ¯¯¯¯¯¯¯¯¯
// - Jesus4Lyf for code assistance.
//
library ChainLightning initializer OnInit uses Lightning, T32, Recycle, Damage
//===========================================================
// DEFAULT CONSTANTS:
//
// The default values used by this system are found here for
// ease of maintenance.
//
globals
private constant real DEFAULT_MAX_HOP_DISTANCE = 300.0
private constant real DEFAULT_TIME_BETWEEN_HOPS = 0.25
private constant real DEFAULT_FADE_TIME = 1.0
private constant real DEFAULT_HOP_FACTOR = 0.8 // Drops 20% per hop.
private constant string DEFAULT_LIGHTNING_TYPE = "CLPB"
private constant integer SOUND_VOLUME = 85 // out of 127.
endglobals
//===========================================================
// FUNCTION INTERFACE: ChainLightning_Callback
//
// This callback is used for each hop made stemming from a
// ChainLightningEx call.
//
public function interface Callback takes integer id, unit target returns nothing
//===========================================================
// NON-CONFIGURABLE CONSTANTS:
//
// These are constants which are not configurables.
//
// If your map already has a global group named "GROUP", you
// may wish to remove the private declaration for it.
//
globals
private constant integer DEFAULT_TICKS_BETWEEN_HOPS = R2I(DEFAULT_TIME_BETWEEN_HOPS/T32_PERIOD)
private group GROUP=CreateGroup() // For those who don't have this.
endglobals
//===========================================================
// IsUnitAlive:
//
// This is here because the normal check for a unit being
// alive is not as effective as this method. Should be inline
// friendly.
//
private function IsUnitAlive takes unit whichUnit returns boolean
return GetWidgetLife(whichUnit)>0.405
endfunction
//===========================================================
// ZAP SOUND:
//
// The basic data for a link of lightning. This is so there
// is minimal array declaration, and faster recycling of unit
// handle ids.
//
globals
private sound ZapSound
endglobals
//! textmacro CL__ZapSound takes TARGET
set ZapSound=CreateSound("Abilities\\Spells\\Orc\\LightningBolt\\LightningBolt.wav",false,true,true,10,10,"SpellsEAX")
call SetSoundDuration(ZapSound,2136)
call SetSoundVolume(ZapSound,SOUND_VOLUME)
call AttachSoundToUnit(ZapSound,$TARGET$)
call StartSound(ZapSound)
call KillSoundWhenDone(ZapSound)
//! endtextmacro
//===========================================================
// FROM CALLBACK SNIPPETS (later):
//
// The globals//locals block from the callback snippets are
// relocated to here due to JassHelper parser limitations.
//
//! runtextmacro CL__CallbackGlobals()
//===========================================================
// DATA DECLARATION:
//
// The basic data for an instance of ChainLightning. This is
// so there is minimal array declaration, and unit handle ids
// are recycled faster.
//
private struct Instance //extends array // JassHelper won't allow this with inheritance.
// Allocator that won't lose efficiency with inheritance.
// Faster than vJass allocator.
private static thistype array recycled
private static integer recycledMax=0
private static integer lastAlloc=0
static method alloc takes nothing returns thistype
if thistype.recycledMax==0 then
set thistype.lastAlloc=thistype.lastAlloc+1
return thistype(thistype.lastAlloc)
endif
set thistype.recycledMax=thistype.recycledMax-1
return thistype.recycled[thistype.recycledMax]
endmethod
method dealloc takes nothing returns nothing
set thistype.recycled[thistype.recycledMax]=this
set thistype.recycledMax=thistype.recycledMax+1
endmethod
// Data
integer hopsLeft
integer ticksToHop
integer ticksPerHop
real fadeTime
real maxHopDistance
unit source
unit caster
real damage
real reductionFactor
player owner
group hit
real r
real g
real b
string which
Callback onHop
boolean hitsEnemies
// Filterfuncs.
//! runtextmacro CL__OnAoE("Enemy","ENEMY")
//! runtextmacro CL__OnAoE("Ally","ALLY")
static method init takes nothing returns nothing
set thistype.FILTER_ON_AOE_ENEMY=Filter(function thistype.onAoEEnemy)
set thistype.FILTER_ON_AOE_ALLY=Filter(function thistype.onAoEAlly)
endmethod
endstruct
// This OnInit function is used to initialise filterfuncs, since
// JassHelper has a shortfall in not letting modules have private
// initializers (causing T32 to steal the onInit method).
private function OnInit takes nothing returns nothing
call Instance.init()
endfunction
//===========================================================
// CALLBACK DECLARATION:
//
// This is all the data and code segments used in the T32
// callback methods. Textmacros are brilliant, because they
// provide functional decomposition without any efficiency
// penalty.
//
// Globals have been used to shorten code (locals also have
// terribly ugly declarations) and provide an efficiency
// boost, as well as eliminate nulling concerns for the unit.
//
// T32 has been used for high efficiency.
//
//! textmacro CL__CallbackGlobals
// This block is moved
globals//locals
private unit Unit
private unit Target
private player Owner
private group Hit
private real X
private real Y
private real X2
private real Y2
private real ThisRange
private real Range
endglobals
//! endtextmacro
//===========================================================
// Callback Snippets
//
//! textmacro CL__OnAoE takes DIPLOMACY, DIPLOMACY_CAPS
private static method onAoE$DIPLOMACY$ takes nothing returns boolean
set Unit=GetFilterUnit()
if IsUnit$DIPLOMACY$(Unit,Owner) and IsUnitAlive(Unit) then
if not (IsUnitInGroup(Unit,Hit) or IsUnitType(Unit,UNIT_TYPE_MAGIC_IMMUNE)) then
set X2=GetUnitX(Unit)-X
set Y2=GetUnitY(Unit)-Y
set ThisRange=X2*X2+Y2*Y2
if ThisRange<Range then
set Range=ThisRange
set Target=Unit
endif
endif
endif
return false
endmethod
static boolexpr FILTER_ON_AOE_$DIPLOMACY_CAPS$
//! endtextmacro
//! textmacro CL__GetTarget takes DIPLOMACY_CAPS
set Hit=this.hit
set Owner=this.owner
set X=GetUnitX(this.source)
set Y=GetUnitY(this.source)
set Range=this.maxHopDistance*this.maxHopDistance
set Target=null
call GroupEnumUnitsInRange(GROUP,X,Y,this.maxHopDistance,thistype.FILTER_ON_AOE_$DIPLOMACY_CAPS$)
if Target==null then
call Group.release(this.hit)
set this.ticksToHop=0
call this.dealloc()
return true
endif
//! endtextmacro
//! textmacro CL__JumpTo takes THIS, TARGET
call Lightning_UnitUnit("CLPB",$THIS$.source,$TARGET$,$THIS$.fadeTime,true)
call Lightning_ColorLast($THIS$.r,$THIS$.g,$THIS$.b)
set $THIS$.source=$TARGET$
call GroupAddUnit($THIS$.hit,$TARGET$)
set $THIS$.ticksToHop=$THIS$.ticksToHop+$THIS$.ticksPerHop
set $THIS$.hopsLeft=$THIS$.hopsLeft-1
if $THIS$.hopsLeft==0 then
call Group.release($THIS$.hit)
set $THIS$.ticksToHop=0
call $THIS$.dealloc()
//endif
//! endtextmacro
//! textmacro CL__DefaultJumpAction takes THIS, TARGET
call Damage_Spell($THIS$.caster,$TARGET$,$THIS$.damage)
set $THIS$.damage=$THIS$.damage*$THIS$.reductionFactor
//! endtextmacro
//! textmacro CL__UpkeepStart
set this.ticksToHop=this.ticksToHop-1
loop
exitwhen this.ticksToHop>0
//endloop
//! endtextmacro
//===========================================================
// T32 Callbacks
//
// One for default Chain Lightning (simple damage which is
// also reduced each hop) and one for an Explicit version,
// in which the user to specify the behavior for each hop.
//
private struct InstanceStandard extends Instance
private method periodic takes nothing returns boolean
//! runtextmacro CL__UpkeepStart()
// loop: Starts for Jumping.
//! runtextmacro CL__GetTarget("ENEMY")
// Zap unit for damage.
//! runtextmacro CL__ZapSound("Target")
//! runtextmacro CL__DefaultJumpAction("this","Target")
// Move instance to unit.
//! runtextmacro CL__JumpTo("this","Target")
// if: No more hops after jump.
return true
endif
endloop
return false
endmethod
implement T32
endstruct
private struct InstanceSpecial extends Instance
private method periodic takes nothing returns boolean
//! runtextmacro CL__UpkeepStart()
// loop: Starts for Jumping.
if this.hitsEnemies then
//! runtextmacro CL__GetTarget("ENEMY")
else
//! runtextmacro CL__GetTarget("ALLY")
endif
call this.onHop.evaluate(this,Target)
// Move instance to unit.
//! runtextmacro CL__JumpTo("this","Target")
// if: No more hops after jump.
return true
endif
endloop
return false
endmethod
implement T32
endstruct
//===========================================================
// PUBLIC INTERFACE:
//
// This is the declaration of all functionality exposed to
// end users. Once again, a global struct variable has been
// used to remove the ugly local declaration, and textmacros
// have been used for efficient functional decomposition.
//
globals//locals
private Instance Data
endglobals
//===========================================================
// Interface Snippets
//
//! textmacro CL__Create
set Data=Instance.alloc()
set Data.hopsLeft=hops
//set this.ticksToHop=0 // Should always be.
set Data.ticksPerHop=DEFAULT_TICKS_BETWEEN_HOPS
set Data.fadeTime=DEFAULT_FADE_TIME
set Data.maxHopDistance=DEFAULT_MAX_HOP_DISTANCE
set Data.source=source
set Data.caster=caster
set Data.owner=GetOwningPlayer(caster)
set Data.hit=Group.get()
set Data.r=1.0
set Data.g=1.0
set Data.b=1.0
set Data.which=whichCode
//! endtextmacro
//===========================================================
// Interface
//
function ChainLightning takes unit caster, unit source, unit target, string whichCode, real damage, integer hops returns nothing
//! runtextmacro CL__Create()
set Data.damage=damage
set Data.reductionFactor=DEFAULT_HOP_FACTOR
// Zap unit for damage.
//! runtextmacro CL__ZapSound("target")
//! runtextmacro CL__DefaultJumpAction("Data","target")
// Move instance to unit.
//! runtextmacro CL__JumpTo("Data","target")
// if: No more hops after jump.
else
call InstanceStandard(Data).startPeriodic()
endif
endfunction
function ChainLightningEx takes unit caster, unit source, string whichCode, Callback onHop, boolean hitsEnemies, integer hops returns integer
//! runtextmacro CL__Create()
set Data.onHop=onHop
set Data.hitsEnemies=hitsEnemies
return Data
endfunction
public function StartLastEx takes unit target returns nothing
call Data.onHop.evaluate(Data,target)
// Move instance to unit.
//! runtextmacro CL__JumpTo("Data","target")
// if: No more hops after jump.
else
call InstanceSpecial(Data).startPeriodic()
endif
endfunction
public function Sound takes unit target returns nothing
//! runtextmacro CL__ZapSound("target")
endfunction
// Let's not clutter our interfaces.
public function ColorLast takes real r, real g, real b returns nothing
set Data.r=r
set Data.g=g
set Data.b=b
call Lightning_ColorLast(r,g,b)
endfunction
public function SetLastTimeBetweenHops takes real time returns nothing
set Data.ticksPerHop=R2I(time/T32_PERIOD)
set Data.ticksToHop=Data.ticksPerHop
endfunction
public function SetlastMaxHopDistance takes real distance returns nothing
set Data.maxHopDistance=distance
endfunction
public function SetLastHopDamageFactor takes real factor returns nothing
set Data.damage=Data.damage/Data.reductionFactor*factor
set Data.reductionFactor=factor
endfunction
//===========================================================
// Note to users:
//
// Keep smiling. God loves you. <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin :D" loading="lazy" data-shortname=":D" />
// Happy mapping.
endlibrary
Updates:
- Version 1.00: Release.