Name | Type | is_array | initial_value |
scope BloodFrenzy
/*************************************************************************************************************
* v1.5d
* by JC Helas
*
* Description:
* Execute a series of lightening-fast at attack on a single target.
*
* Requires:
* CTL and WorldBounds - Nestharus
* RegisterPlayerUnit - Magtheridon96
* SpelEffectEvent - Bribe
*
* How to Import:
* - Open File\Preferences and enable "Automatically creates unknown variables while pasting trigger data".
* - Copy This Folder.
* - And dont forget to copy the objects.
* - Then Done!!!
*
************************************************************************************************************/
globals
/********************************************************/
/* */
/* CONFIGURES */
/* */
/********************************************************/
/* Determine the ability ID of spell. */
/* In getting the data of an ability at object editor */
/* you have to press CTRL+D and simply click back to */
/* return on normal view. */
private constant integer ABILITY_ID = 'A000'
/********************************************************/
/* Determine the base amount of slash. */
/* Each slash has random angle also but if the target */
/* caster will change target if an enemy is near */
/* but if no one, then the series will stop. */
private constant integer SLASH_BASE = 3
/********************************************************/
/* Determine the additional amount of slash per level. */
/* Each level of ability will increase the slash amount */
/* by this integer. BASE + ( THIS * Level of Ability ) */
private constant integer SLASH_LVL = 2
/********************************************************/
/* Determine the base amount of damage. */
/* Damage happens when in each slash ends. */
private constant real DAMAGE_BASE = 25.0
/********************************************************/
/* Determine the additional amount damage per level. */
/* Each level of ability will increase the amount of */
/* damage by this real. BASE + ( THIS * LEVEL ) */
private constant real DAMAGE_LVL = 25.0
/********************************************************/
/* Determine the forward speed of caster. */
/* This must lower than DISTANCE_START or else the spell*/
/* will play unpleasing, im very sorry if im not able */
/* to change this into matrix. */
private constant real SPEED_FORWARD = 50.0
/********************************************************/
/* Determine the starting distance of caster to target */
/* per slash. */
private constant real DISTANCE_START = 300.0
/********************************************************/
/* Determine the distance search of enemy when target */
/* is dead. */
private constant real NEXT_TARGET_SEARCH = 600.0
/********************************************************/
/* Determine the default alpha of caster. */
/* This will be the alpha vertex of caster after */
/* finishing a series. */
private constant integer CASTER_APLHA_DEFAULT = 255
/********************************************************/
/* Determine the starting alpha of caster */
/* in each slash. */
private constant integer CASTER_APLHA_START = 255
/********************************************************/
/* Determine the ending alpha of caster in each slash. */
private constant integer CASTER_APLHA_END = 0
/********************************************************/
/* Determine the animation of caster in each slash. */
/* In order to get the unit index move you have */
/* test them with the native function which is */
/* SetUnitAnimationByIndex(WhichUnit,Index of Animation)*/
private constant integer SLASH_ANIMATION_INDEX= 6
/********************************************************/
/* Determine the animation speed of caster */
/* in each slash. */
private constant real SLASH_ANIMATION_SPEED= 2.5
/********************************************************/
/* Determine the attack type of damaging */
/* in all slash. */
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_NORMAL
/********************************************************/
/* Determine the damage type of damaging */
/* in all slash. */
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
/********************************************************/
/* Determine the weapon type of damaging */
/* in all slash. */
private constant weapontype WEAPON_TYPE = null
/********************************************************/
/* Determine the hit effect for target */
/* in each slash. */
private constant string HIT_EFFECT = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
/********************************************************/
/* Determine the HIT_EFFECT attachment location */
/* for target. */
private constant string TARGET_ATTACH = "origin"
/********************************************************/
/* Determine the effect for caster */
/* in each slash. */
private constant string CASTER_EFFECT = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
/********************************************************/
/* Determine the CASTER_EFFECT attachement location */
/* for caster. */
private constant string CASTER_ATTACH = "origin"
/********************************************************/
/* Determine the type of lightning. */
private constant string LIGHTNIG_TYPE = "CLPB"
/* */
/* END OF CONFIGURES */
/* */
/********************************************************/
endglobals
native UnitAlive takes unit u returns boolean
private function Slash takes integer lvl returns integer
return SLASH_BASE+(SLASH_LVL*lvl)
endfunction
private function Damage takes integer lvl returns real
return DAMAGE_BASE+(DAMAGE_LVL*lvl)
endfunction
private function Filter takes unit t,player p returns boolean
return UnitAlive(t) and not(IsUnitType(t,UNIT_TYPE_MAGIC_IMMUNE)) and not(IsUnitType(t,UNIT_TYPE_STRUCTURE)) and not(IsUnitAlly(t,p))
endfunction
private function Fly takes unit u returns boolean
return UnitAddAbility(u,'Amrf') and UnitRemoveAbility(u,'Amrf')
endfunction
private function CheckXY takes real x,real y returns boolean
return x<WorldBounds.maxX and x>WorldBounds.minX and y<WorldBounds.maxY and y>WorldBounds.minY
endfunction
private struct spell
integer count
player owner
lightning l
unit caster
unit target
real angle
real dist
real dmg
real xs
real ys
real zs
static constant real pendist=DISTANCE_START*2
static constant group grp=CreateGroup()
static integer ix=0
static integer array ic
implement CTL
local integer i=1
local real rate
local real xc
local real yc
local real xt
local real yt
local real z
implement CTLExpire
loop
exitwhen i>ix
set this=ic[i]
if count>0 and UnitAlive(caster) and target!=null then
set xt=GetUnitX(target)
set yt=GetUnitY(target)
if dist<pendist then
set dist=dist+SPEED_FORWARD
set rate=(1.0/pendist)*dist
set xc=xt-DISTANCE_START*Cos(angle*bj_DEGTORAD)
set yc=yt-DISTANCE_START*Sin(angle*bj_DEGTORAD)
set xc=xc+dist*Cos(angle*bj_DEGTORAD)
set yc=yc+dist*Sin(angle*bj_DEGTORAD)
set z=GetUnitFlyHeight(target)
if CheckXY(xc,yc) then
call SetUnitX(caster,xc)
call SetUnitY(caster,yc)
endif
call SetUnitFacing(caster,angle)
call SetUnitFlyHeight(caster,z,0.0)
call SetUnitVertexColor(caster,255,255,255,R2I(CASTER_APLHA_START*(1.0-rate))+CASTER_APLHA_END)
if dist<=DISTANCE_START then
call MoveLightningEx(l,false,xc,yc,z,xt,yt,z)
call SetLightningColor(l,1,1,1,1-(rate*2.0))
endif
else
call UnitDamageTarget(caster,target,dmg,true,true,ATTACK_TYPE,DAMAGE_TYPE,WEAPON_TYPE)
call DestroyEffect(AddSpecialEffectTarget(CASTER_EFFECT,caster,CASTER_ATTACH))
call DestroyEffect(AddSpecialEffectTarget(HIT_EFFECT,target,TARGET_ATTACH))
call SetUnitAnimationByIndex(caster,SLASH_ANIMATION_INDEX)
set angle=angle+GetRandomReal(-180.0,180.0)
if angle<0 then
set angle=angle+360.0
endif
set dist=0.0
set count=count-1
if count>0 and not(UnitAlive(target)) then
call GroupEnumUnitsInRange(grp,xt,yt,NEXT_TARGET_SEARCH,null)
loop
set target=FirstOfGroup(grp)
exitwhen target==null or Filter(target,owner)
call GroupRemoveUnit(grp,target)
endloop
call GroupClear(grp)
if target==null then
set count=0
elseif GetUnitFlyHeight(target)>0.0 and Fly(caster) then
endif
endif
endif
else
call SetUnitVertexColor(caster,255,255,255,CASTER_APLHA_DEFAULT)
call SetUnitPosition(caster,xs,ys)
call SetUnitFlyHeight(caster,zs,0)
call SetUnitTimeScale(caster,1.0)
call SetUnitPathing(caster,true)
call DestroyLightning(l)
set i=DeIndex(i)
endif
set i=i+1
endloop
implement CTLEnd
private static method DeIndex takes integer i returns integer
local spell this=ic[i]
call destroy()
set ic[i]=ic[ix]
set ix=ix-1
return i-1
endmethod
private static method Index takes nothing returns spell
local spell this=create()
set ix=ix+1
set ic[ix]=this
return this
endmethod
private static method onCast takes nothing returns nothing
local spell this
local unit t=GetSpellTargetUnit()
local unit c=GetTriggerUnit()
local player p=GetOwningPlayer(c)
local integer lvl
local real z
if Filter(t,p) then
set lvl=GetUnitAbilityLevel(c,ABILITY_ID)
set this=Index()
set caster=c
set target=t
set owner=p
set angle=GetRandomReal(0.0,360.0)
set dist=0.0
set xs=GetUnitX(c)
set ys=GetUnitY(c)
set zs=GetUnitFlyHeight(c)
set z=GetUnitFlyHeight(t)
set count=Slash(lvl)
set dmg=Damage(lvl)
set l=AddLightningEx(LIGHTNIG_TYPE,false,xs,ys,zs,GetUnitX(target),GetUnitY(target),z)
call DestroyEffect(AddSpecialEffectTarget(CASTER_EFFECT,caster,CASTER_ATTACH))
call SetUnitAnimationByIndex(caster,SLASH_ANIMATION_INDEX)
call SetUnitTimeScale(caster,SLASH_ANIMATION_SPEED)
call SetUnitPathing(caster,false)
if z>0.0 and Fly(c) then
endif
endif
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(ABILITY_ID,function thistype.onCast)
endmethod
endstruct
endscope
library_once WorldBounds /* v2.0.0.0
************************************************************************************
*
* struct WorldBounds extends array
* readonly static integer maxX
* readonly static integer maxY
* readonly static integer minX
* readonly static integer minY
* readonly static integer centerX
* readonly static integer centerY
* readonly static rect world
* readonly static region worldRegion
*
************************************************************************************/
private module WorldBoundInit
private static method onInit takes nothing returns nothing
set world=GetWorldBounds()
set maxX=R2I(GetRectMaxX(world))
set maxY=R2I(GetRectMaxY(world))
set minX=R2I(GetRectMinX(world))
set minY=R2I(GetRectMinY(world))
set centerX=R2I((maxX+minX)/2)
set centerY=R2I((minY+maxY)/2)
set worldRegion=CreateRegion()
call RegionAddRect(worldRegion,world)
endmethod
endmodule
struct WorldBounds extends array
readonly static integer maxX
readonly static integer maxY
readonly static integer minX
readonly static integer minY
readonly static integer centerX
readonly static integer centerY
readonly static rect world
readonly static region worldRegion
implement WorldBoundInit
endstruct
endlibrary
library CTL /* v1.2.0.3
*************************************************************************************
*
* CTL or Constant Timer Loop provides a loop for constant merged timers of timeout .03125
*
* Similar to T32 but pauses timer when no structs have instances and removes structs
* from timer trigger when those structs have no instances.
*
* This can also create new timers after destroying a previous timer and generates less
* code in the module. It also generates no triggers so long as the module is implemented
* at the top of the struct.
*
************************************************************************************
*
* module CTL
*
* Allows creation/destruction of timers in a struct. Provides instancing of those timers.
*
* - static method create takes nothing returns thistype
* - method destroy takes nothing returns nothing
*
* CTL (optional)
* local variables, code before running any timers
* CTLExpire (not optional)
* timer code
* CTLNull (optional)
* null any locals, runs after all timers
* CTLEnd (not optional)
*
* module CT32
*
* Converts struct into a timer group. Allows the timer group to be started and stopped.
* Instancing and looping through active timers is up to the user.
*
* - static method start takes nothing returns nothing
* - static method stop takes nothing returns nothing
*
* CT32 (not optional)
* timer code
* CT32End (not optional)
*
* struct TimerGroup32 extends array
*
* Allows for the creation of timer groups. Timer instancing and looping is entirely up
* to the user.
*
* - static method create takes code func returns thistype
* - method destroy takes nothing returns nothing
* - method start takes nothing returns nothing
* - method stop takes nothing returns nothing
*
************************************************************************************/
globals
private integer tgc = 0 //timer group count
private integer array tgr //timer group recycler
private integer ic=0 //instance count
private integer tc=0 //timer count
private integer array rf //root first
private integer array n //next
private integer array p //previous
private integer array th //timer head
private integer array ns //next stack
private trigger t=CreateTrigger()
private timer m=CreateTimer()
private triggercondition array ct
private conditionfunc array rc
private boolean array e32 //enabled
private integer array i32r //ct32 recycler
private integer i32cr = 0 //ct32 count recycler
private boolean array ir32 //is recycling
private boolean array id32 //is destroying
endglobals
private function E takes nothing returns nothing
local integer i=ns[0]
set ns[0]=0
loop
exitwhen 0==i
if (0==p[i]) then
if (0==n[i]) then
call TriggerRemoveCondition(t,ct[th[i]])
set ct[th[i]]=null
set tc=tc-1
set rf[th[i]]=0
else
set rf[th[i]]=n[i]
set p[n[i]]=0
endif
else
set p[n[i]]=p[i]
set n[p[i]]=n[i]
endif
set n[i]=n[0]
set n[0]=i
set i=ns[i]
endloop
loop
exitwhen 0 == i32cr
set i32cr = i32cr - 1
set i = i32r[i32cr]
if (not e32[i]) then
call TriggerRemoveCondition(t,ct[i])
set ct[i] = null
if (id32[i]) then
set tgr[i] = tgr[0]
set tgr[0] = i
set id32[i] = false
endif
set ir32[i] = false
endif
endloop
if (0==tc) then
call PauseTimer(m)
else
call TriggerEvaluate(t)
endif
endfunction
private function CT takes integer r returns integer
local integer i
local integer f
if (0==n[0]) then
set i=ic+1
set ic=i
else
set i=n[0]
set n[0]=n[i]
endif
set th[i]=r
set ns[i]=-1
set f=rf[r]
if (0==f) then
set n[i]=0
set p[i]=0
set rf[r]=i
set ct[r]=TriggerAddCondition(t,rc[r])
//set ct[r] = null
if (0==tc) then
call TimerStart(m,.031250000,true,function E)
endif
set tc=tc+1
else
set n[i]=f
set p[i]=0
set p[f]=i
set rf[r]=i
endif
return i
endfunction
private function DT takes integer t returns nothing
debug if (0>ns[t]) then
set ns[t]=ns[0]
set ns[0]=t
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"TIMER LOOP ERROR: ATTEMPT TO DESTROY NULL TIMER")
debug endif
endfunction
private function A takes code c returns integer
local integer i = tgr[0]
if (0 == i) then
set i = tgc + 1
set tgc = i
else
set tgr[0] = tgr[i]
endif
set rc[i]=Condition(c)
return i
endfunction
private function A32 takes integer i returns nothing
if (not (e32[i] or id32[i])) then
if (ir32[i]) then
set ir32[i] = false
else
set ct[i] = TriggerAddCondition(t, rc[i])
endif
if (0 == tc) then
call TimerStart(m,.031250000,true,function E)
endif
set tc = tc + 1
set e32[i] = true
endif
endfunction
private function SR32 takes integer i returns nothing
if (e32[i]) then
if (not (ir32[i] or id32[i])) then
set i32r[i32cr] = i
set i32cr = i32cr + 1
set ir32[i] = true
endif
set e32[i] = false
set tc = tc - 1
endif
endfunction
private function DT32 takes integer i returns nothing
if (not id32[i]) then
if (not ir32[i]) then
set ir32[i] = true
set tc = tc - 1
set i32r[i32cr] = i
set i32cr = i32cr + 1
set e32[i] = false
endif
set id32[i] = true
endif
endfunction
private keyword r
private keyword e
module CTL
static integer rctl32
static method create takes nothing returns thistype
return CT(rctl32)
endmethod
method destroy takes nothing returns nothing
call DT(this)
endmethod
static method ectl32 takes nothing returns boolean
local thistype this=rf[rctl32]
endmodule
module CTLExpire
implement CTL
loop
exitwhen 0==this
endmodule
module CTLNull
set this=n[this]
endloop
endmodule
module CTLEnd
implement CTLNull
return false
endmethod
private static method onInit takes nothing returns nothing
set rctl32 = A(function thistype.ectl32)
endmethod
endmodule
module CT32
static integer rctl32
static method start takes nothing returns nothing
call A32(rctl32)
endmethod
static method stop takes nothing returns nothing
call SR32(rctl32)
endmethod
static method ectl32 takes nothing returns boolean
endmodule
module CT32End
return false
endmethod
private static method onInit takes nothing returns nothing
set rctl32 = A(function thistype.ectl32)
endmethod
endmodule
struct TimerGroup32 extends array
static method create takes code c returns thistype
return A(c)
endmethod
method destroy takes nothing returns nothing
call DT32(this)
endmethod
method start takes nothing returns nothing
call A32(this)
endmethod
method stop takes nothing returns nothing
call SR32(this)
endmethod
endstruct
endlibrary
/**************************************************************
*
* RegisterPlayerUnitEvent
* v5.1.0.1
* By Magtheridon96
*
* I would like to give a special thanks to Bribe, azlier
* and BBQ for improving this library. For modularity, it only
* supports player unit events.
*
* Functions passed to RegisterPlayerUnitEvent must either
* return a boolean (false) or nothing. (Which is a Pro)
*
* Warning:
* --------
*
* - Don't use TriggerSleepAction inside registered code.
* - Don't destroy a trigger unless you really know what you're doing.
*
* API:
* ----
*
* - function RegisterPlayerUnitEvent takes playerunitevent whichEvent, code whichFunction returns nothing
* - Registers code that will execute when an event fires.
* - function RegisterPlayerUnitEventForPlayer takes playerunitevent whichEvent, code whichFunction, player whichPlayer returns nothing
* - Registers code that will execute when an event fires for a certain player.
* - function GetPlayerUnitEventTrigger takes playerunitevent whichEvent returns trigger
* - Returns the trigger corresponding to ALL functions of a playerunitevent.
*
**************************************************************/
library RegisterPlayerUnitEvent // Special Thanks to Bribe and azlier
globals
private trigger array t
endglobals
function RegisterPlayerUnitEvent takes playerunitevent p, code c returns nothing
local integer i = GetHandleId(p)
local integer k = 15
if t[i] == null then
set t[i] = CreateTrigger()
loop
call TriggerRegisterPlayerUnitEvent(t[i], Player(k), p, null)
exitwhen k == 0
set k = k - 1
endloop
endif
call TriggerAddCondition(t[i], Filter(c))
endfunction
function RegisterPlayerUnitEventForPlayer takes playerunitevent p, code c, player pl returns nothing
local integer i = 16 * GetHandleId(p) + GetPlayerId(pl)
if t[i] == null then
set t[i] = CreateTrigger()
call TriggerRegisterPlayerUnitEvent(t[i], pl, p, null)
endif
call TriggerAddCondition(t[i], Filter(c))
endfunction
function GetPlayerUnitEventTrigger takes playerunitevent p returns trigger
return t[GetHandleId(p)]
endfunction
endlibrary
//============================================================================
// SpellEffectEvent
// - Version 1.1.0.0
//
// API
// ---
// RegisterSpellEffectEvent(integer abil, code onCast)
//
// Requires
// --------
// RegisterPlayerUnitEvent: hiveworkshop.com/forums/showthread.php?t=203338
//
// Optional
// --------
// Table: hiveworkshop.com/forums/showthread.php?t=188084
//
library SpellEffectEvent requires RegisterPlayerUnitEvent, optional Table
//============================================================================
private module M
static if LIBRARY_Table then
static Table tb
else
static hashtable ht = InitHashtable()
endif
static method onCast takes nothing returns nothing
static if LIBRARY_Table then
call TriggerEvaluate(.tb.trigger[GetSpellAbilityId()])
else
call TriggerEvaluate(LoadTriggerHandle(.ht, 0, GetSpellAbilityId()))
endif
endmethod
private static method onInit takes nothing returns nothing
static if LIBRARY_Table then
set .tb = Table.create()
endif
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function thistype.onCast)
endmethod
endmodule
//============================================================================
private struct S extends array
implement M
endstruct
//============================================================================
function RegisterSpellEffectEvent takes integer abil, code onCast returns nothing
static if LIBRARY_Table then
if not S.tb.handle.has(abil) then
set S.tb.trigger[abil] = CreateTrigger()
endif
call TriggerAddCondition(S.tb.trigger[abil], Filter(onCast))
else
if not HaveSavedHandle(S.ht, 0, abil) then
call SaveTriggerHandle(S.ht, 0, abil, CreateTrigger())
endif
call TriggerAddCondition(LoadTriggerHandle(S.ht, 0, abil), Filter(onCast))
endif
endfunction
endlibrary