Name | Type | is_array | initial_value |
//TESH.scrollpos=84
//TESH.alwaysfold=0
//////////////////////////////////
//LASER v1.2a //
// by: Nherwyziant //
//==============================//
//Requires: //
// T32 //
// GT //
// Recycle //
//==============================//
//Credits: //
// Jesus4Lyf //
// Nestharus //
// Vexorian //
//==============================//
//How to copy //
// Copy the dummy unit //
// Copy the codes below //
// Set values to the desired //
//////////////////////////////////
scope Laser
native UnitAlive takes unit id returns boolean
globals
private constant integer RAWCODE = 'A000' //~Spell Rawcode
private constant integer DUMMY = 'h000' //~Shadow Dummy Rawcode
private constant string L_FX = "AFOD" //~The lightning effect
private constant string L_FX2 = "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnMissile.mdl" //~The effect on the happy trails
private constant string L_FX3 = "Abilities\\Weapons\\DemolisherFireMissile\\DemolisherFireMissile.mdl" //~The effect on hit
private constant string ANIMATION = "spell third" //The animation of the shadow
private constant real L_HEIGHT = 225 //~Height of lightning. Just right for Balnazzar :D
private constant real AOE = 150 //~AoE of lightning
private constant real DURATION = .75 //~DURATION OF SPELL ^___^
private constant real SHADOWLIFE = 2.5 //~The duration of the shadow
private constant attacktype ATK_TYPE = ATTACK_TYPE_HERO //~Attack type
private constant damagetype DMG_TYPE = DAMAGE_TYPE_MAGIC //~Damage type
endglobals
private function RANGE takes integer lvl returns real
return 1000. + (lvl * 500.)
endfunction
private function DMG takes integer lvl returns real
return lvl * 75.
endfunction
//Do not touch the remaining part, or else you will be a victim of a killer.
private struct Data
private static group GROUP = CreateGroup()
private static thistype this
private static conditionfunc cf
unit caster
unit shadow
player p
group dmgUnits
real x
real y
real z
real tx
real ty
real tz
real angle
real range
real speed
real dmg
real cos
real sin
integer lvl
integer ticks
lightning l
private static method DoDamage takes nothing returns boolean
local thistype this = thistype.this
local unit u = GetFilterUnit()
if IsUnitEnemy(u,.p) and UnitAlive(u) and IsUnitType(u,UNIT_TYPE_STRUCTURE) == false and not IsUnitInGroup(u,.dmgUnits) then
call UnitDamageTarget(.caster,u,.dmg,true,false,ATK_TYPE,DMG_TYPE,null)
call DestroyEffect(AddSpecialEffectTarget(L_FX3,u,"origin"))
call GroupAddUnit(.dmgUnits,u)
endif
return false
endmethod
private method periodic takes nothing returns nothing
if .ticks >= T32_Tick then
set .tx = .tx + .cos
set .ty = .ty + .sin
set .tz = GetLocationZ(Location(.tx,.ty))
if UnitAlive(.caster) then
call MoveLightningEx(.l,true,.x,.y,.z,.tx,.ty,.tz)
call DestroyEffect(AddSpecialEffect(L_FX2,.tx,.ty))
set thistype.this = this
call GroupEnumUnitsInRange(thistype.GROUP,.tx,.ty,AOE,thistype.cf)
else
call DestroyLightning(.l)
endif
else
call DestroyLightning(.l)
call .stopPeriodic()
call Group.release(.dmgUnits)
set .caster = null
set .l = null
endif
endmethod
implement T32x
private static method Action takes nothing returns boolean
local thistype this = thistype.create()
set .caster = GetTriggerUnit()
set .p = GetOwningPlayer(.caster)
set .x = GetUnitX(.caster)
set .y = GetUnitY(.caster)
set .z = GetLocationZ(Location(.x,.y)) + L_HEIGHT + GetUnitFlyHeight(.caster)
set .tx = GetSpellTargetX()
set .ty = GetSpellTargetY()
set .tz = GetLocationZ(Location(.tx,.ty))
set .lvl = GetUnitAbilityLevel(.caster,RAWCODE)
set .angle = Atan2(.ty-.y,.tx-.x)
set .range = RANGE(.lvl)
set .speed = .range / R2I(DURATION/T32_PERIOD)
set .dmg = DMG(.lvl)
set .cos = .speed * Cos(.angle)
set .sin = .speed * Sin(.angle)
set .l = AddLightningEx(L_FX,true,.x,.y,.z,.x,.y,.tz)
set .ticks = T32_Tick + R2I(DURATION/T32_PERIOD)
set .dmgUnits = Group.get()
set .tx = .x
set .ty = .y
call .startPeriodic()
return false
endmethod
private static method Action2 takes nothing returns boolean
local thistype this = thistype.create()
set .caster = GetTriggerUnit()
set .p = GetOwningPlayer(.caster)
set .x = GetUnitX(.caster)
set .y = GetUnitY(.caster)
set .tx = GetSpellTargetX()
set .ty = GetSpellTargetY()
set .angle = Atan2(.ty-.y,.tx-.x)
set .shadow = CreateUnit(.p,DUMMY,.x,.y,.angle*bj_RADTODEG)
call SetUnitAnimation(.shadow,ANIMATION)
call SetUnitVertexColor(.shadow,100,100,100,50)
call SetUnitScale(.shadow,1.5,1.5,1.5)
call UnitApplyTimedLife(.shadow,'BTLF',SHADOWLIFE)
call UnitAddAbility(.shadow,'Amrf')
call UnitRemoveAbility(.shadow,'Amrf')
call SetUnitFlyHeight(.shadow,GetUnitFlyHeight(.caster),0)
//Optional only.==========================================================//
call PlaySoundAtPointBJ(gg_snd_Ama_Firen_Mah_Lazar,100,Location(.x,.y),.z)
//========================================================================//
set .shadow = null
set .caster = null
return false
endmethod
private static method onInit takes nothing returns nothing
call GT_AddStartsEffectAction(function thistype.Action,RAWCODE)
call GT_AddBeginsCastingAction(function thistype.Action2,RAWCODE)
set thistype.cf = Condition(function thistype.DoDamage)
endmethod
endstruct
endscope
//TESH.scrollpos=45
//TESH.alwaysfold=0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~ Timer32 ~~ By Jesus4Lyf ~~ Version 1.06 ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// What is Timer32?
// - Timer32 implements a fully optimised timer loop for a struct.
// - Instances can be added to the loop, which will call .periodic every
// PERIOD until .stopPeriodic() is called.
//
// =Pros=
// - Efficient.
// - Simple.
//
// =Cons=
// - Only allows one period.
// - The called method must be named ".periodic".
//
// Methods:
// - struct.startPeriodic()
// - struct.stopPeriodic()
//
// - private method periodic takes nothing returns nothing
//
// This must be defined in structs that implement Periodic Module.
// It will be executed by the module every PERIOD until .stopPeriodic() is called.
// Put "implement T32x" BELOW this method.
//
// Modules:
// - T32x
// Has no safety on .stopPeriodic or .startPeriodic (except debug messages
// to warn).
//
// - T32xs
// Has safety on .stopPeriodic and .startPeriodic so if they are called
// multiple times, or while otherwise are already stopped/started respectively,
// no error will occur, the call will be ignored.
//
// - T32
// The original, old version of the T32 module. This remains for backwards
// compatability, and is deprecated. The periodic method must return a boolean,
// false to continue running or true to stop.
//
// Details:
// - Uses one timer.
//
// - Do not, within a .periodic method, follow a .stopPeriodic call with a
// .startPeriodic call.
//
// How to import:
// - Create a trigger named T32.
// - Convert it to custom text and replace the whole trigger text with this.
//
// Thanks:
// - Infinitegde for finding a bug in the debug message that actually altered
// system operation (when in debug mode).
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library T32 initializer OnInit
globals
public constant real PERIOD=0.03125
public constant integer FPS=R2I(1/PERIOD)
public integer Tick=0 // very useful.
//==============================================================================
private trigger Trig=CreateTrigger()
endglobals
//==============================================================================
// The standard T32 module, T32x.
//
module T32x
private thistype next
private thistype prev
private static method PeriodicLoop takes nothing returns boolean
local thistype this=thistype(0).next
loop
exitwhen this==0
call this.periodic()
set this=this.next
endloop
return false
endmethod
method startPeriodic takes nothing returns nothing
debug if this.prev!=0 or thistype(0).next==this then
debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had startPeriodic called while already running!")
debug endif
set thistype(0).next.prev=this
set this.next=thistype(0).next
set thistype(0).next=this
set this.prev=thistype(0)
endmethod
method stopPeriodic takes nothing returns nothing
debug if this.prev==0 and thistype(0).next!=this then
debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had stopPeriodic called while not running!")
debug endif
// This is some real magic.
set this.prev.next=this.next
set this.next.prev=this.prev
// This will even work for the starting element.
debug set this.prev=0
endmethod
private static method onInit takes nothing returns nothing
call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop))
endmethod
endmodule
//==============================================================================
// The standard T32 module with added safety checks on .startPeriodic() and
// .stopPeriodic(), T32xs.
//
module T32xs
private thistype next
private thistype prev
private boolean runningPeriodic
private static method PeriodicLoop takes nothing returns boolean
local thistype this=thistype(0).next
loop
exitwhen this==0
call this.periodic()
set this=this.next
endloop
return false
endmethod
method startPeriodic takes nothing returns nothing
if not this.runningPeriodic then
set thistype(0).next.prev=this
set this.next=thistype(0).next
set thistype(0).next=this
set this.prev=thistype(0)
set this.runningPeriodic=true
endif
endmethod
method stopPeriodic takes nothing returns nothing
if this.runningPeriodic then
// This is some real magic.
set this.prev.next=this.next
set this.next.prev=this.prev
// This will even work for the starting element.
set this.runningPeriodic=false
endif
endmethod
private static method onInit takes nothing returns nothing
call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop))
endmethod
endmodule
//==============================================================================
// The original T32 module, for backwards compatability only.
//
module T32 // deprecated.
private thistype next
private thistype prev
private static method PeriodicLoop takes nothing returns boolean
local thistype this=thistype(0).next
loop
exitwhen this==0
if this.periodic() then
// This is some real magic.
set this.prev.next=this.next
set this.next.prev=this.prev
// This will even work for the starting element.
debug set this.prev=0
endif
set this=this.next
endloop
return false
endmethod
method startPeriodic takes nothing returns nothing
debug if this.prev!=0 or thistype(0).next==this then
debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had startPeriodic called while already running!")
debug endif
set thistype(0).next.prev=this
set this.next=thistype(0).next
set thistype(0).next=this
set this.prev=thistype(0)
endmethod
private static method onInit takes nothing returns nothing
call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop))
endmethod
endmodule
//==============================================================================
// System Core.
//
private function OnExpire takes nothing returns nothing
set Tick=Tick+1
call TriggerEvaluate(Trig)
endfunction
private function OnInit takes nothing returns nothing
call TimerStart(CreateTimer(),PERIOD,true,function OnExpire)
endfunction
endlibrary
//TESH.scrollpos=174
//TESH.alwaysfold=0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~ GT ~~ GTrigger ~~ By Jesus4Lyf ~~ Version 1.05 ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// What is GTrigger?
// - GTrigger is an event system that replaces the cumbersome WC3
// event system.
// - GTrigger only launches the necessary threads instead of x threads,
// where x is the number of times the event type occurs in the map.
//
// =Pros=
// - Instead of having 16 events (for "16" players) per use of an,
// event type, you have 0 per use and 16 total for that event type.
// - If you have 100 events of one type in your map, instead of firing
// 100 triggers each time any spell is cast, you fire only what's needed.
// - GTrigger is faster to code with, more efficient to execute, and just
// better programming practises and nicer code all round.
//
// =Cons=
// - If a trigger with a GTrigger event is destroyed, it must have its
// event unregistered first or it will leak an event (slows firing down).
// - Shouldn't use "wait" actions anywhere in the triggers.
//
// Functions:
// // General
// - GT_UnregisterTriggeringEvent()
//
// // Ability events
// - GT_RegisterStartsEffectEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_RegisterBeginsChanellingEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_RegisterBeginsCastingEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_RegisterStopsCastingEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_RegisterFinishesCastingEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_RegisterLearnsAbilityEvent(trigger, abilityid) (returns the trigger passed in)
// // Order events // (can use String2OrderIdBJ("OrderString") for orderid
// - GT_RegisterTargetOrderEvent(trigger, orderid) (returns the trigger passed in)
// - GT_RegisterPointOrderEvent(trigger, orderid) (returns the trigger passed in)
// - GT_RegisterNoTargetOrderEvent(trigger, orderid) (returns the trigger passed in)
// // Item events
// - GT_RegisterItemUsedEvent(trigger, itemtypeid) (returns the trigger passed in)
// - GT_RegisterItemAcquiredEvent(trigger, itemtypeid) (returns the trigger passed in)
// - GT_RegisterItemDroppedEvent(trigger, itemtypeid) (returns the trigger passed in)
// // Unit events
// - GT_RegisterUnitDiesEvent(trigger, unittypeid) (returns the trigger passed in)
//
// // Ability Events
// - GT_UnregisterSpellEffectEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_UnregisterBeginsChanellingEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_UnregisterBeginsCastingEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_UnregisterStopsCastingEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_UnregisterFinishesCastingEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_UnregisterLearnsAbilityEvent(trigger, abilityid) (returns the trigger passed in)
// // Order events // (can use String2OrderIdBJ("OrderString") for orderid
// - GT_UnregisterTargetOrderEvent(trigger, orderid) (returns the trigger passed in)
// - GT_UnregisterPointOrderEvent(trigger, orderid) (returns the trigger passed in)
// - GT_UnregisterNoTargetOrderEvent(trigger, orderid) (returns the trigger passed in)
// // Item events
// - GT_UnregisterItemUsedEvent(trigger, itemtypeid) (returns the trigger passed in)
// - GT_UnregisterItemAcquiredEvent(trigger, itemtypeid) (returns the trigger passed in)
// - GT_UnregisterItemDroppedEvent(trigger, itemtypeid) (returns the trigger passed in)
// // Unit events
// - GT_UnregisterUnitDiesEvent(trigger, unittypeid) (returns the trigger passed in)
//
// Alternative interface (not recommended):
// If you aren't familiar with how this works, you shouldn't use it.
// All funcs must return false. (That is the only reason it isn't recommended.)
// // General
// - GT_RemoveTriggeringAction() // Use this to remove actions.
// // Ability Events
// - GT_AddStartsEffectAction(func, abilityid)
// - GT_AddBeginsChanellingAction(func, abilityid)
// - GT_AddBeginsCastingAction(func, abilityid)
// - GT_AddStopsCastingAction(func, abilityid)
// - GT_AddFinishesCastingAction(func, abilityid)
// - GT_AddLearnsAbilityAction(func, abilityid)
// // Order events // (can use String2OrderIdBJ("OrderString") for orderid
// - GT_AddTargetOrderAction(func, orderid)
// - GT_AddPointOrderAction(func, orderid)
// - GT_AddNoTargetOrderAction(func, orderid)
// // Item events
// - GT_AddItemUsedAction(func, itemtypeid)
// - GT_AddItemAcquiredAction(func, itemtypeid)
// - GT_AddItemDroppedAction(func, itemtypeid)
// // Unit events
// - GT_AddUnitDiesAction(func, unittypeid)
//
// Details:
// - Due to the storage method, only 8191 GTrigger events are possible at any one time.
//
// Thanks:
// - Daxtreme: For voluntarily testing this system and the UnitDies event idea.
// - kenny!: For the Order and Learns Ability event ideas.
//
// How to import:
// - Create a trigger named GT.
// - Convert it to custom text and replace the whole trigger text with this.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library GT initializer Init
//////////////
// Pointers //
////////////////////////////////////////////////////////////////////////////
// Assigned to abilities, and point to trigger grouping linked lists.
//
// Use:
// GetPointer --> int (pointer)
// FreePointer(int (pointer))
// set PointerTarget[int (pointer)]=int (list link)
// PointerTarget[int (pointer)] --> int (list link)
globals
// Pointer
private integer array PointerTarget
private integer PointerMax=0
// Spare Pointer Stack
private integer array NextPointer
private integer NextPointerMaxPlusOne=1
endglobals
private function GetPointer takes nothing returns integer
if NextPointerMaxPlusOne==1 then
set PointerMax=PointerMax+1
return PointerMax
endif
set NextPointerMaxPlusOne=NextPointerMaxPlusOne-1
return NextPointer[NextPointerMaxPlusOne]
endfunction
private function FreePointer takes integer pointer returns nothing
set PointerTarget[pointer]=0
set NextPointer[NextPointerMaxPlusOne]=pointer
set NextPointerMaxPlusOne=NextPointerMaxPlusOne+1
endfunction
///////////////////////////////////
// Trigger Grouping Linked Lists //
////////////////////////////////////////////////////////////////////////////
// Contains a chain of triggers to be executed together.
//
// Use:
// GetMem() --> int (mem)
// FreeMem(int (mem))
// Link(int (pointer), int (mem))
// Unlink(int (pointer), int (mem))
globals
// Spare Link Stack
private integer array NextMem
private integer NextMemMaxPlusOne=1
// Linked list
private trigger array Trig
private integer array Next
private integer array Prev
private integer TrigMax=0
endglobals
private function GetMem takes nothing returns integer
if NextMemMaxPlusOne==1 then
set TrigMax=TrigMax+1
return TrigMax
endif
set NextMemMaxPlusOne=NextMemMaxPlusOne-1
return NextMem[NextMemMaxPlusOne]
endfunction
private function FreeMem takes integer i returns nothing
set Trig[i]=null
set NextMem[NextMemMaxPlusOne]=i
set NextMemMaxPlusOne=NextMemMaxPlusOne+1
endfunction
// Linked list functionality
// NOTE: This means "Next" must be loaded BEFORE executing the trigger, which could delete the current link.
private function Link takes integer pointer, integer new returns nothing
set Prev[new]=0
set Next[new]=PointerTarget[pointer]
set Prev[PointerTarget[pointer]]=new
set PointerTarget[pointer]=new
endfunction
private function Unlink takes integer pointer, integer rem returns nothing
if Prev[rem]==0 then
set PointerTarget[pointer]=Next[rem]
set Prev[Next[rem]]=0
endif
set Next[Prev[rem]]=Next[rem]
set Prev[Next[rem]]=Prev[rem]
endfunction
//////////////////////
// GTrigger General //
////////////////////////////////////////////////////////////////////////////
// Only contains the UnregisterTriggeringEvent action for public use.
globals
boolean UnregisterLastEvent=false
endglobals
public function UnregisterTriggeringEvent takes nothing returns nothing
set UnregisterLastEvent=true
endfunction
/////////////////////////////////////
// GTrigger Ability Implementation //
////////////////////////////////////////////////////////////////////////////
// The nasty textmacro implementation of special "All Players" events.
//! textmacro SetupSpecialAllPlayersEvent takes NAME, EVENT, GETSPECIAL
globals
private trigger $NAME$Trigger=CreateTrigger()
// Extendable arrays
private integer array $NAME$AbilityIdA
private integer array $NAME$ListPointerA
private integer array $NAME$AbilityIdB
private integer array $NAME$ListPointerB
private integer array $NAME$AbilityIdC
private integer array $NAME$ListPointerC
private integer array $NAME$AbilityIdD
private integer array $NAME$ListPointerD
private integer array $NAME$AbilityIdE
private integer array $NAME$ListPointerE
endglobals
globals//locals
private integer GetOrCreateListPointer$NAME$AbilHashed
endglobals
private function GetOrCreate$NAME$ListPointer takes integer abil returns integer
set GetOrCreateListPointer$NAME$AbilHashed=abil-(abil/8191)*8191
if $NAME$AbilityIdA[GetOrCreateListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerA[GetOrCreateListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdA[GetOrCreateListPointer$NAME$AbilHashed]<1 then // Empty
set $NAME$AbilityIdA[GetOrCreateListPointer$NAME$AbilHashed]=abil
set $NAME$ListPointerA[GetOrCreateListPointer$NAME$AbilHashed]=GetPointer()
return $NAME$ListPointerA[GetOrCreateListPointer$NAME$AbilHashed]
endif
if $NAME$AbilityIdB[GetOrCreateListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerB[GetOrCreateListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdB[GetOrCreateListPointer$NAME$AbilHashed]<1 then // Empty
set $NAME$AbilityIdB[GetOrCreateListPointer$NAME$AbilHashed]=abil
set $NAME$ListPointerB[GetOrCreateListPointer$NAME$AbilHashed]=GetPointer()
return $NAME$ListPointerB[GetOrCreateListPointer$NAME$AbilHashed]
endif
if $NAME$AbilityIdC[GetOrCreateListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerC[GetOrCreateListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdC[GetOrCreateListPointer$NAME$AbilHashed]<1 then // Empty
set $NAME$AbilityIdC[GetOrCreateListPointer$NAME$AbilHashed]=abil
set $NAME$ListPointerC[GetOrCreateListPointer$NAME$AbilHashed]=GetPointer()
return $NAME$ListPointerC[GetOrCreateListPointer$NAME$AbilHashed]
endif
if $NAME$AbilityIdD[GetOrCreateListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerD[GetOrCreateListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdD[GetOrCreateListPointer$NAME$AbilHashed]<1 then // Empty
set $NAME$AbilityIdD[GetOrCreateListPointer$NAME$AbilHashed]=abil
set $NAME$ListPointerD[GetOrCreateListPointer$NAME$AbilHashed]=GetPointer()
return $NAME$ListPointerD[GetOrCreateListPointer$NAME$AbilHashed]
endif
if $NAME$AbilityIdE[GetOrCreateListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerE[GetOrCreateListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdE[GetOrCreateListPointer$NAME$AbilHashed]<1 then // Empty
set $NAME$AbilityIdE[GetOrCreateListPointer$NAME$AbilHashed]=abil
set $NAME$ListPointerE[GetOrCreateListPointer$NAME$AbilHashed]=GetPointer()
return $NAME$ListPointerE[GetOrCreateListPointer$NAME$AbilHashed]
endif
call BJDebugMsg("GTrigger Error: Ran out of storage locations for pointers on object "+GetObjectName(abil)+"!")
set PointerTarget[0]=0
return 0
endfunction
globals//locals
private integer GetListPointer$NAME$AbilHashed
endglobals
private function Get$NAME$ListPointer takes integer abil returns integer
set GetListPointer$NAME$AbilHashed=abil-(abil/8191)*8191
if $NAME$AbilityIdA[GetListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerA[GetListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdA[GetListPointer$NAME$AbilHashed]<1 then // Empty
set PointerTarget[0]=0 // Make sure.
return 0
endif
if $NAME$AbilityIdB[GetListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerB[GetListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdB[GetListPointer$NAME$AbilHashed]<1 then // Empty
set PointerTarget[0]=0 // Make sure.
return 0
endif
if $NAME$AbilityIdC[GetListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerC[GetListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdC[GetListPointer$NAME$AbilHashed]<1 then // Empty
set PointerTarget[0]=0 // Make sure.
return 0
endif
if $NAME$AbilityIdD[GetListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerD[GetListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdD[GetListPointer$NAME$AbilHashed]<1 then // Empty
set PointerTarget[0]=0 // Make sure.
return 0
endif
if $NAME$AbilityIdE[GetListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerE[GetListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdE[GetListPointer$NAME$AbilHashed]<1 then // Empty
set PointerTarget[0]=0 // Make sure.
return 0
endif
call BJDebugMsg("GTrigger Error: Ran out of storage locations for pointers at ability "+GetObjectName(abil)+"!")
set PointerTarget[0]=0
return 0
endfunction
globals//locals
private integer Register$NAME$Mem
endglobals
public function Register$NAME$Event takes trigger t, integer abil returns trigger
set Register$NAME$Mem=GetMem()
set Trig[Register$NAME$Mem]=t
call Link(GetOrCreate$NAME$ListPointer(abil),Register$NAME$Mem)
return t
endfunction
globals//locals
private integer Unregister$NAME$Pointer
private integer Unregister$NAME$Mem
endglobals
public function Unregister$NAME$Event takes trigger t, integer abil returns trigger
set Unregister$NAME$Pointer=Get$NAME$ListPointer(abil)
set Unregister$NAME$Mem=PointerTarget[Unregister$NAME$Pointer]
loop
exitwhen Trig[Unregister$NAME$Mem]==t
if Unregister$NAME$Mem==0 then
return t // Not found.
endif
set Unregister$NAME$Mem=Next[Unregister$NAME$Mem]
endloop
call Unlink(Unregister$NAME$Pointer,Unregister$NAME$Mem)
call FreeMem(Unregister$NAME$Mem)
return t
endfunction
private function Trigger$NAME$Event takes nothing returns boolean
local integer Trigger$NAME$Pointer=Get$NAME$ListPointer($GETSPECIAL$)
local integer Trigger$NAME$Mem=PointerTarget[Trigger$NAME$Pointer]
local integer Trigger$NAME$NextMem
set UnregisterLastEvent=false
loop
exitwhen Trigger$NAME$Mem<1
set Trigger$NAME$NextMem=Next[Trigger$NAME$Mem]
if TriggerEvaluate(Trig[Trigger$NAME$Mem]) then
call TriggerExecute(Trig[Trigger$NAME$Mem])
endif
if UnregisterLastEvent then
set UnregisterLastEvent=false
call Unlink(Trigger$NAME$Pointer,Trigger$NAME$Mem)
call FreeMem(Trigger$NAME$Mem)
endif
set Trigger$NAME$Mem=Trigger$NAME$NextMem
endloop
return false
endfunction
private function Init$NAME$ takes nothing returns nothing
local integer i=bj_MAX_PLAYER_SLOTS
call TriggerAddCondition($NAME$Trigger,Condition(function Trigger$NAME$Event))
loop
set i=i-1
call TriggerRegisterPlayerUnitEvent($NAME$Trigger,Player(i),EVENT_PLAYER_$EVENT$,null)
exitwhen i==0
endloop
endfunction
//! endtextmacro
//! runtextmacro SetupSpecialAllPlayersEvent("StartsEffect", "UNIT_SPELL_EFFECT", "GetSpellAbilityId()")
//! runtextmacro SetupSpecialAllPlayersEvent("BeginsChanelling", "UNIT_SPELL_CHANNEL", "GetSpellAbilityId()")
//! runtextmacro SetupSpecialAllPlayersEvent("BeginsCasting", "UNIT_SPELL_CAST", "GetSpellAbilityId()")
//! runtextmacro SetupSpecialAllPlayersEvent("StopsCasting", "UNIT_SPELL_ENDCAST", "GetSpellAbilityId()")
//! runtextmacro SetupSpecialAllPlayersEvent("FinishesCasting", "UNIT_SPELL_FINISH", "GetSpellAbilityId()")
//! runtextmacro SetupSpecialAllPlayersEvent("TargetOrder", "UNIT_ISSUED_TARGET_ORDER", "GetIssuedOrderId()")
//! runtextmacro SetupSpecialAllPlayersEvent("PointOrder", "UNIT_ISSUED_POINT_ORDER", "GetIssuedOrderId()")
//! runtextmacro SetupSpecialAllPlayersEvent("NoTargetOrder", "UNIT_ISSUED_ORDER", "GetIssuedOrderId()")
//! runtextmacro SetupSpecialAllPlayersEvent("ItemUsed", "UNIT_USE_ITEM", "GetItemTypeId(GetManipulatedItem())")
//! runtextmacro SetupSpecialAllPlayersEvent("ItemAcquired", "UNIT_PICKUP_ITEM", "GetItemTypeId(GetManipulatedItem())")
//! runtextmacro SetupSpecialAllPlayersEvent("ItemDropped", "UNIT_DROP_ITEM", "GetItemTypeId(GetManipulatedItem())")
//! runtextmacro SetupSpecialAllPlayersEvent("UnitDies", "UNIT_DEATH", "GetUnitTypeId(GetTriggerUnit())")
//! runtextmacro SetupSpecialAllPlayersEvent("LearnsAbility", "HERO_SKILL", "GetLearnedSkill()")
// Note to self: Remember to update the Init function.
/////////////////////////////////////////
// GTrigger All Players Implementation //
////////////////////////////////////////////////////////////////////////////
// The textmacro implementation of other "All Players" events.
//! textmacro SetupAllPlayersEvent takes NAME, EVENT
globals
private trigger $NAME$Trigger=CreateTrigger()
private integer $NAME$ListPointer=0
endglobals
globals//locals
private integer Register$NAME$Mem
endglobals
public function Register$NAME$Event takes trigger t returns trigger
set Register$NAME$Mem=GetMem()
set Trig[Register$NAME$Mem]=t
call Link($NAME$ListPointer,Register$NAME$Mem)
return t
endfunction
globals//locals
private integer Unregister$NAME$Pointer
private integer Unregister$NAME$Mem
endglobals
public function Unregister$NAME$Event takes trigger t returns trigger
set Unregister$NAME$Mem=PointerTarget[$NAME$ListPointer]
loop
exitwhen Trig[Unregister$NAME$Mem]==t
if Unregister$NAME$Mem==0 then
return t // Not found.
endif
set Unregister$NAME$Mem=Next[Unregister$NAME$Mem]
endloop
call Unlink($NAME$ListPointer,Unregister$NAME$Mem)
call FreeMem(Unregister$NAME$Mem)
return t
endfunction
private function Trigger$NAME$Event takes nothing returns boolean
local integer Trigger$NAME$Mem=PointerTarget[$NAME$ListPointer]
local integer Trigger$NAME$NextMem
set UnregisterLastEvent=false
loop
exitwhen Trigger$NAME$Mem<1
set Trigger$NAME$NextMem=Next[Trigger$NAME$Mem]
if TriggerEvaluate(Trig[Trigger$NAME$Mem]) then
call TriggerExecute(Trig[Trigger$NAME$Mem])
endif
if UnregisterLastEvent then
set UnregisterLastEvent=false
call Unlink($NAME$ListPointer,Trigger$NAME$Mem)
call FreeMem(Trigger$NAME$Mem)
endif
set Trigger$NAME$Mem=Trigger$NAME$NextMem
endloop
return false
endfunction
private function Init$NAME$ takes nothing returns nothing
local integer i=bj_MAX_PLAYER_SLOTS
call TriggerAddCondition($NAME$Trigger,Condition(function Trigger$NAME$Event))
loop
set i=i-1
call TriggerRegisterPlayerUnitEvent($NAME$Trigger,Player(i),EVENT_PLAYER_UNIT_$EVENT$,null)
exitwhen i==0
endloop
// Initialise the pointer.
set $NAME$ListPointer=GetPointer()
endfunction
//! endtextmacro
// Old: //! runtextmacro SetupAllPlayersEvent("AnyUnitDies", "DEATH")
private function Init takes nothing returns nothing
// Ability events
call InitStartsEffect()
call InitBeginsChanelling()
call InitBeginsCasting()
call InitStopsCasting()
call InitFinishesCasting()
call InitLearnsAbility()
// Order events
call InitTargetOrder()
call InitPointOrder()
call InitNoTargetOrder()
// Item events
call InitItemUsed()
call InitItemAcquired()
call InitItemDropped()
// Unit events
call InitUnitDies()
endfunction
//////////////
// Wrappers //
////////////////////////////////////////////////////////////////////////////
// Wraps it up, for those who really want this interface.
// General
public function RemoveTriggeringAction takes nothing returns nothing
call UnregisterTriggeringEvent()
call DestroyTrigger(GetTriggeringTrigger())
endfunction
// Special All Player Events
//! textmacro AddSpecialAllPlayersWrapper takes EVENT
public function Add$EVENT$Action takes code func, integer special returns nothing
call TriggerAddCondition(Register$EVENT$Event(CreateTrigger(),special),Condition(func))
endfunction
//! endtextmacro
//! runtextmacro AddSpecialAllPlayersWrapper("StartsEffect")
//! runtextmacro AddSpecialAllPlayersWrapper("BeginsChanelling")
//! runtextmacro AddSpecialAllPlayersWrapper("BeginsCasting")
//! runtextmacro AddSpecialAllPlayersWrapper("StopsCasting")
//! runtextmacro AddSpecialAllPlayersWrapper("FinishesCasting")
//! runtextmacro AddSpecialAllPlayersWrapper("TargetOrder")
//! runtextmacro AddSpecialAllPlayersWrapper("PointOrder")
//! runtextmacro AddSpecialAllPlayersWrapper("NoTargetOrder")
//! runtextmacro AddSpecialAllPlayersWrapper("ItemUsed")
//! runtextmacro AddSpecialAllPlayersWrapper("ItemAcquired")
//! runtextmacro AddSpecialAllPlayersWrapper("ItemDropped")
//! runtextmacro AddSpecialAllPlayersWrapper("UnitDies")
//! runtextmacro AddSpecialAllPlayersWrapper("LearnsAbility")
// Note to self: Remember to update the Init function.
// All Player Events
//! textmacro AddAllPlayersWrapper takes EVENT
public function Add$EVENT$Action takes code func returns nothing
call TriggerAddCondition(Register$EVENT$Event(CreateTrigger()),Condition(func))
endfunction
//! endtextmacro
// Old: //! runtextmacro AddAllPlayersWrapper("AnyUnitDies")
endlibrary
//TESH.scrollpos=3
//TESH.alwaysfold=0
library Recycle
//settings
globals
public constant boolean AUTO_CLEAR = true
endglobals
/*Utility Information
//===================================================================
Name: Recycle
Version: 6.0
Author: Nestharus
-Help from Jesus4Lyf for initial designs
Description:
What does it do-
Recycles handles so that when getting new handles of the same type,
a recycled handle can be returned instead of creating a new handle. This
increases map performance.
Requirements: NA
Installation: NA
Variables:
------------------------------------------------------------------
AUTO_CLEAN-
If true, will automatically clear out recycled handles (GroupClear,
PauseTimer) at a slight performance hit.
Functions:
------------------------------------------------------------------
-get returns type
will return the type
Timer.get()
Group.get()
ex-
timer t = Timer.get()
-release(type h)
Will release the type and stop it.
Timer.release(h)
Group.release(h)
ex-
timer t = Timer.get()
Timer.release(t)
------------------------------------------------------------------*/
//! textmacro CREATE_STACK takes name, type, clean, create
struct $name$ extends array
public $type$ handles
public static integer index = 0
public static method release takes $type$ h returns nothing
static if DEBUG_MODE then
if h == null then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "ERROR - Recycle: Freed null handle.")
endif
if $name$.index > 8190 then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "ERROR - Recycle: Overfilled recycle stack (8191 released objects)!")
endif
endif
static if AUTO_CLEAR then
$clean$
endif
set $name$[$name$.index].handles = h
set $name$.index = $name$.index + 1
endmethod
public static method get takes nothing returns $type$
if $name$.index == 0 then
return $create$
endif
set $name$.index = $name$.index - 1
return $name$[$name$.index].handles
endmethod
endstruct
//! endtextmacro
//! runtextmacro CREATE_STACK("Timer", "timer", "call PauseTimer(h)", "CreateTimer()")
//! runtextmacro CREATE_STACK("Group", "group", "call GroupClear(h)", "CreateGroup()")
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
//////////////////////////////////
//LASER //
// by: Nherwyziant //
//==============================//
//Requires: //
// TimerUtils //
//==============================//
//Credits: //
// Vexorian //
//==============================//
//How to copy //
// Copy the dummy unit //
// Copy the codes below //
// Set values to the desired //
//==============================//
//Range is constant 2000, //
//due to some reason. //
//I'll try to fix this soon. //
//////////////////////////////////
scope Laser initializer INIT
globals
private constant integer RAWCODE = 'A000' //~The spell rawcode
private constant integer DUMMY = 'h000' //~The dummy rawcode
private constant real INCREMENT = 25 //~The spell speed
private constant real TIMEOUT = 0.01 //~The spell timer
private constant real AREA = 150 //~Area of Effect
private constant string FX = "AFOD" //~The lightning effect
private constant string FX2 = "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnMissile.mdl" //~The effect when lightning is moving
private constant string FX3 = "Abilities\\Weapons\\DemolisherFireMissile\\DemolisherFireMissile.mdl" //~The effect when enemy is hit
endglobals
private function Damage takes integer lvl returns integer
return 75*lvl
endfunction
//========Do not touch the remaining, or else you will be part of JigSaw's show.======\\
globals
private real MaxX
private real MinX
private real MaxY
private real MinY
endglobals
private function cond takes nothing returns boolean
return GetSpellAbilityId() == RAWCODE
endfunction
private struct data
unit u
unit f
location ul
location tl
location d
location ll
real tf
lightning l
timer t
group g1 = CreateGroup()
group g2 = CreateGroup()
private method onDestroy takes nothing returns nothing
call ReleaseTimer(.t)
call RemoveLocation(.ul)
call RemoveLocation(.tl)
call RemoveLocation(.ll)
call RemoveLocation(.d)
call DestroyLightning(.l)
call GroupClear(.g1)
call GroupClear(.g2)
set .ll = null
set .ul = null
set .tl = null
set .u = null
set .l = null
endmethod
endstruct
private function CheckMe takes location dist returns boolean
if GetLocationX(dist) < MaxX and GetLocationX(dist) > MinX and GetLocationY(dist) < MaxY and GetLocationY(dist) > MinY then
return true
else
return false
endif
endfunction
private function MoveIt takes nothing returns nothing
local data d = GetTimerData(GetExpiredTimer())
local real m = GetLocationX(d.ll) + INCREMENT * Cos(d.tf * bj_DEGTORAD)
local real n = GetLocationY(d.ll) + INCREMENT * Sin(d.tf * bj_DEGTORAD)
local real dx = GetLocationX(d.d) - GetLocationX(d.ll)
local real dy = GetLocationY(d.d) - GetLocationY(d.ll)
set d.ll = Location(m,n)
if SquareRoot(dx * dx + dy * dy) <= 0 or CheckMe(d.ll) == false then
call d.destroy()
else
call MoveLightningEx(d.l, true, GetLocationX(d.ul), GetLocationY(d.ul),GetLocationZ(d.ul)+225,GetLocationX(d.ll), GetLocationY(d.ll), GetLocationZ(d.ll))
call GroupClear(d.g1)
call DestroyEffect(AddSpecialEffect(FX2,GetLocationX(d.ll),GetLocationY(d.ll)))
call GroupEnumUnitsInRange(d.g1, GetLocationX(d.ll), GetLocationY(d.ll), AREA, null)
loop
set d.f = FirstOfGroup(d.g1)
exitwhen d.f == null
if IsUnitAlly(d.f, GetOwningPlayer(d.u)) == false and IsUnitType(d.f, UNIT_TYPE_STRUCTURE) == false and IsUnitInGroup(d.f, d.g2) == false and GetWidgetLife(d.f) > 0.405 then
call UnitDamageTarget(d.u, d.f,Damage(GetUnitAbilityLevel(d.u,RAWCODE)), true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_MAGIC, null)
call DestroyEffect(AddSpecialEffectTarget(FX3,d.f,"origin"))
call GroupAddUnit(d.g2, d.f)
endif
call GroupRemoveUnit(d.g1, d.f)
endloop
endif
endfunction
private function Action takes nothing returns nothing
local real x
local real y
local data d = data.create()
set d.u = GetTriggerUnit()
set d.ul = GetUnitLoc(d.u)
set d.ll = GetUnitLoc(d.u)
set d.tl = GetSpellTargetLoc()
set d.tf = bj_RADTODEG * Atan2(GetLocationY(d.tl) - GetLocationY(d.ul), GetLocationX(d.tl) - GetLocationX(d.ul))
set x = GetLocationX(d.ul) + 2000 * Cos(d.tf * bj_DEGTORAD)
set y = GetLocationY(d.ul) + 2000 * Sin(d.tf * bj_DEGTORAD)
set d.d = Location(x,y)
set d.l = AddLightningEx(FX, true, GetLocationX(d.ul), GetLocationY(d.ul), GetLocationZ(d.ul)+225,GetLocationX(d.ul), GetLocationY(d.ul), GetLocationZ(d.ul))
set d.t = NewTimer()
call SetTimerData(d.t, d)
call TimerStart(d.t, TIMEOUT, true, function MoveIt)
endfunction
private function Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local location l = GetUnitLoc(u)
local location t = GetSpellTargetLoc()
local unit e
call PlaySoundAtPointBJ(gg_snd_Ama_Firen_Mah_Lazar,100,l,0)
call CreateTextTagUnitBJ( "Ama Firen Mah Lazar",u,0,10,100,100,100,0)
call SetTextTagPermanentBJ(bj_lastCreatedTextTag,false)
call SetTextTagLifespanBJ(bj_lastCreatedTextTag,2)
call SetTextTagFadepointBJ(bj_lastCreatedTextTag,1)
call SetTextTagVelocityBJ(bj_lastCreatedTextTag,64,90)
set e = CreateUnitAtLoc(Player(0),DUMMY,l,bj_RADTODEG * Atan2(GetLocationY(t) - GetLocationY(l), GetLocationX(t) - GetLocationX(l)))
call SetUnitAnimation(e,"spell third")
call SetUnitVertexColor(e,100,100,100,50)
call SetUnitScale(e,1.5,1.5,1.5)
call UnitApplyTimedLife(e,'BTLF',2.5)
call RemoveLocation(l)
call RemoveLocation(t)
set t = null
set l = null
set e = null
set u = null
endfunction
private function INIT takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
loop
call TriggerRegisterPlayerUnitEvent(t, Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition(t, Condition(function cond))
call TriggerAddAction(t, function Action)
set t = CreateTrigger()
set i = 0
loop
call TriggerRegisterPlayerUnitEvent(t, Player(i),EVENT_PLAYER_UNIT_SPELL_CHANNEL,null)
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition(t, Condition(function cond))
call TriggerAddAction(t, function Actions)
set MaxX = GetRectMaxX(bj_mapInitialPlayableArea) - 64
set MaxY = GetRectMaxY(bj_mapInitialPlayableArea) - 64
set MinX = GetRectMinX(bj_mapInitialPlayableArea) + 64
set MinY = GetRectMinY(bj_mapInitialPlayableArea) + 64
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
//////////////////////////////////
//LASER v1.1 //
// by: Nherwyziant //
//==============================//
//Requires: //
// T32 //
// GT //
// Recycle //
//==============================//
//Credits: //
// Jesus4Lyf //
// Nestharus //
// Vexorian //
//==============================//
//How to copy //
// Copy the dummy unit //
// Copy the codes below //
// Set values to the desired //
//////////////////////////////////
scope Laser
native UnitAlive takes unit id returns boolean
globals
private constant integer RAWCODE = 'A000' //~Spell Rawcode
private constant integer DUMMY = 'h000' //~Shadow Dummy Rawcode
private constant string L_FX = "AFOD" //~The lightning effect
private constant string L_FX2 = "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnMissile.mdl" //~The effect on the happy trails
private constant string L_FX3 = "Abilities\\Weapons\\DemolisherFireMissile\\DemolisherFireMissile.mdl" //~The effect on hit
private constant real L_HEIGHT = 225 //~Height of lightning. Just right for Balnazzar :D
private constant real AOE = 150 //~AoE of lightning
private constant real DURATION = .75 // DURATION OF SPELL ^___^
private constant attacktype ATK_TYPE = ATTACK_TYPE_HERO //~Attack type
private constant damagetype DMG_TYPE = DAMAGE_TYPE_MAGIC //~Damage type
endglobals
private function RANGE takes integer lvl returns real
return 1000. + (lvl * 500.)
endfunction
private function DMG takes integer lvl returns real
return lvl * 75.
endfunction
//Do not touch the remaining part, or else you will be a victim of a killer.
private struct Data
private static group GROUP = CreateGroup()
private static thistype this
private static conditionfunc cf
unit caster
unit shadow
player p
group dmgUnits
real x
real y
real z
real tx
real ty
real tz
real angle
real range
real speed
real dmg
real cos
real sin
integer lvl
integer ticks
lightning l
private static method DoDamage takes nothing returns boolean
local thistype this = thistype.this
local unit u = GetFilterUnit()
if IsUnitEnemy(u,.p) and UnitAlive(u) and IsUnitType(u,UNIT_TYPE_STRUCTURE) == false and not IsUnitInGroup(u,.dmgUnits) then
call UnitDamageTarget(.caster,u,.dmg,true,false,ATK_TYPE,DMG_TYPE,null)
call DestroyEffect(AddSpecialEffectTarget(L_FX3,u,"origin"))
call GroupAddUnit(.dmgUnits,u)
endif
return false
endmethod
private method periodic takes nothing returns nothing
if .ticks >= T32_Tick then
set .tx = .tx + .cos
set .ty = .ty + .sin
set .tz = GetLocationZ(Location(.tx,.ty))
if UnitAlive(.caster) then
call MoveLightningEx(.l,true,.x,.y,.z,.tx,.ty,.tz)
call DestroyEffect(AddSpecialEffect(L_FX2,.tx,.ty))
set thistype.this = this
call GroupEnumUnitsInRange(thistype.GROUP,.tx,.ty,AOE,thistype.cf)
else
call DestroyLightning(.l)
endif
else
call DestroyLightning(.l)
call Group.release(.dmgUnits)
set .caster = null
set .l = null
endif
endmethod
implement T32x
private static method Action takes nothing returns boolean
local thistype this = thistype.create()
set .caster = GetTriggerUnit()
set .p = GetOwningPlayer(.caster)
set .x = GetUnitX(.caster)
set .y = GetUnitY(.caster)
set .z = GetLocationZ(Location(.x,.y)) + L_HEIGHT
set .tx = GetSpellTargetX()
set .ty = GetSpellTargetY()
set .tz = GetLocationZ(Location(.tx,.ty))
set .lvl = GetUnitAbilityLevel(.caster,RAWCODE)
set .angle = Atan2(.ty-.y,.tx-.x)
set .range = RANGE(.lvl)
set .speed = .range / R2I(DURATION/T32_PERIOD)
set .dmg = DMG(.lvl)
set .cos = .speed * Cos(.angle)
set .sin = .speed * Sin(.angle)
set .l = AddLightningEx(L_FX,true,.x,.y,.z,.x,.y,.tz)
set .ticks = T32_Tick + R2I(DURATION/T32_PERIOD)
set .dmgUnits = Group.get()
set .tx = .x
set .ty = .y
call .startPeriodic()
return false
endmethod
private static method Action2 takes nothing returns boolean
local thistype this = thistype.create()
set .caster = GetTriggerUnit()
set .p = GetOwningPlayer(.caster)
set .x = GetUnitX(.caster)
set .y = GetUnitY(.caster)
set .tx = GetSpellTargetX()
set .ty = GetSpellTargetY()
set .angle = Atan2(.ty-.y,.tx-.x)
set .shadow = CreateUnit(.p,DUMMY,.x,.y,.angle*bj_RADTODEG)
call SetUnitAnimation(.shadow,"spell third")
call SetUnitVertexColor(.shadow,100,100,100,50)
call SetUnitScale(.shadow,1.5,1.5,1.5)
call UnitApplyTimedLife(.shadow,'BTLF',2.5)
//Optional only.==========================================================//
call PlaySoundAtPointBJ(gg_snd_Ama_Firen_Mah_Lazar,100,Location(.x,.y),.z)
//========================================================================//
set .shadow = null
set .caster = null
return false
endmethod
private static method onInit takes nothing returns nothing
call GT_AddStartsEffectAction(function thistype.Action,RAWCODE)
call GT_AddBeginsCastingAction(function thistype.Action2,RAWCODE)
set thistype.cf = Condition(function thistype.DoDamage)
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
library LOLTest
function Jump takes unit u,integer i returns nothing
call UnitAddAbility(u,'Amrf')
call UnitRemoveAbility(u,'Amrf')
call SetUnitFlyHeight(u,i,500)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
function B takes nothing returns nothing
call UnitResetCooldown(gg_unit_Uvar_0000)
call SetUnitLifePercentBJ(gg_unit_Uvar_0000,100)
call SetUnitManaPercentBJ(gg_unit_Uvar_0000,100)
endfunction
function InitTrig_Refresh takes nothing returns nothing
local trigger g=CreateTrigger()
call TriggerRegisterPlayerEvent(g,Player(0),EVENT_PLAYER_END_CINEMATIC)
call TriggerAddAction(g,function B)
endfunction