kingkingyyk3
Visitor (Welcome to the Jungle, Baby!)
- Reaction score
- 216
Attack Effect Handling, v1.0.4
JASS:
library AEH initializer Init requires Damage
/*
AEH - Attack Effect Handling.
v1.0.4
by kingking
=============
What is AEH?
=============
AEH makes your life on handling attack effect(Lifesteal, Mana Burn, etc) easier.
It can restrict attack effect from being triggered, if you want.
Imagine, you want units that have mana burn not to get lifesteal.
AEH is aimed to solve that.
===========
APIs :
===========
Module :
implement AEH
Static Method :
AEH_filter(DamageSource,DamagedUnit,EventDamage)-> boolean
- Return true will make AEH create a new instance of struct.
AEH_register(string key)
- Assign the struct to AEH type(key).
AEH_setTypeCompatible(string key)
- Add the effect into compatible list.
AEH_setTypePrioriy(string key, integer priority)
- The higher the priority, the faster the type of struct will be executed.
Methods :
AEH_onCreate()-> boolean
**If return true, lower priority of AEH struct will not be executed.
AEH_onDestroy()
- For your struct destroying needs.
** Optional.
Members :
unit : attacker, target
real : damage
Static Member :
AEH_autoDestroy
- If set to true, then the struct will be destroyed automatically after AEH_onCreate.
- If set to false, then you have to destroy it manually through .destroy().
** True as default.
============================
Usage Example (With Heal) :
============================
struct Lifesteal
private static method AEH_filter takes unit attacker, unit target, real damage returns boolean
return GetUnitAbilityLevel(damager,'A000')>0
endmethod
private method AEH_onCreate takes nothing returns boolean
call HealUnit(this.attacker,this.attacker,damage*0.2,HEAL_TYPE_LIFESTEAL)
return true
endmethod
private static method onInit takes nothing returns nothing
call thistype.AEH_setTypePriority("Lifesteal",1)
call thistype.AEH_register("Lifesteal")
endmethod
implement AEH
endstruct
=============
Requires :
=============
Jasshelper v0.A.2.B or later
Damage by Jesus4Lyf
========================
Implementation steps :
========================
- Implement Damage to your map.
- Copy the trigger to your map.
- Adjust the fire condition if you wished. */
function FireCondition takes unit attacker, unit target returns boolean
return Damage_IsAttack()
endfunction
/* - Enjoy! */
globals
private hashtable hasht=InitHashtable()
private trigger DamageTrig=CreateTrigger()
private unit DamageSource=null
private unit DamagedUnit=null
private real EventDamage=0.0
endglobals
private function FireTrig takes trigger trig, unit u1, unit u2, real dam returns boolean
local unit oldu1=DamageSource
local unit oldu2=DamagedUnit
local real olddam=EventDamage
local boolean boo
set DamageSource=u1
set DamagedUnit=u2
set EventDamage=dam
set boo=TriggerEvaluate(trig)
set DamageSource=oldu1
set DamagedUnit=oldu2
set EventDamage=olddam
set oldu1=null
set oldu2=null
return boo
endfunction
private struct StringList
readonly string s
readonly thistype prev
readonly thistype next
static method createList takes nothing returns thistype
local thistype this=thistype.allocate()
set this.prev=this
set this.next=this
return this
endmethod
method addString takes string s returns nothing
local thistype node
if not HaveSavedBoolean(hasht,-this,StringHash(s)) then
set node=thistype.allocate()
set node.s=s
set this.prev.next=node
set node.prev=this.prev
set node.next=this
set this.prev=node
call SaveBoolean(hasht,-this,StringHash(s),true)
endif
endmethod
method copyList takes thistype list returns nothing
local thistype listx=list
set list=list.next
loop
exitwhen list==listx
call this.addString(list.s)
set list=list.next
endloop
endmethod
method isStringExists takes string s returns boolean
return LoadBoolean(hasht,-this,StringHash(s))
endmethod
method chainDestroy takes nothing returns nothing
local thistype ori=this
set this=this.next
loop
exitwhen this==ori
set this.prev.next=this.next
set this.next.prev=this.prev
call this.destroy()
set this=this.next
endloop
call this.destroy()
call FlushChildHashtable(hasht,-this)
endmethod
endstruct
private struct Field
/*
Field at here, means a group of node.
The nodes in group have the same keyword.
*/
private trigger trig
private string word
private thistype next
private thistype prev
private thistype nextx
private thistype prevx
private integer priorityx
private StringList s
private static method autoLink takes thistype head, thistype node returns nothing
local thistype this=head
set this.prev.next=node
set node.prev=this.prev
set node.next=this
set this.prev=node
endmethod
private static method autoLinkX takes thistype node returns nothing
local thistype this=thistype(0).nextx
loop
if node.priorityx>=this.priorityx then
set this.prevx.nextx=node
set node.prevx=this.prevx
set node.nextx=this
set this.prevx=node
return
endif
set this=this.nextx
endloop
endmethod
method setTrue takes string w returns nothing
local string s=this.word
if this.s==0 then
set this.s=StringList.createList()
endif
call this.s.addString(w)
set this=LoadInteger(hasht,StringHash(w),0)
if this==0 then
set this=thistype.allocate()
set this.word=w
set this.prev=this
set this.next=this
call SaveInteger(hasht,StringHash(w),0,this)
call thistype.autoLinkX(this)
endif
if this.s==0 then
set this.s=StringList.createList()
endif
call this.s.addString(s)
set s=null
endmethod
static method addTrig takes trigger trig, string w returns thistype
local thistype this=LoadInteger(hasht,StringHash(w),0)
local thistype new
if this==0 then
set this=thistype.allocate()
set this.word=w
set this.prev=this
set this.next=this
call SaveInteger(hasht,StringHash(w),0,this)
call thistype.autoLinkX(this)
endif
set new=thistype.allocate()
set new.word=w
set new.trig=trig
call thistype.autoLink(this,new)
return this
endmethod
static method setFieldPriority takes string w, integer priority returns thistype
local thistype this=LoadInteger(hasht,StringHash(w),0)
if this==0 then
set this=thistype.allocate()
set this.word=w
set this.prev=this
set this.next=this
call SaveInteger(hasht,StringHash(w),0,this)
else
set this.prevx.nextx=this.nextx
set this.nextx.prevx=this.prevx
endif
set this.priorityx=priority
call thistype.autoLinkX(this)
return this
endmethod
private method fireLocalTrig takes unit u1, unit u2, real r returns boolean
local thistype ori=this
local boolean boo=false
set this=this.next
loop
exitwhen this==ori
if FireTrig(this.trig,u1,u2,r) then
set boo=true
endif
set this=this.next
endloop
return boo
endmethod
static method fireFieldTrig takes nothing returns boolean
local thistype this=thistype(0).nextx
local thistype array fired
local integer firedCount=0
local boolean isFired=false
local integer i
local StringList sl=StringList.create()
loop
exitwhen this==0 or isFired
if this.fireLocalTrig(GetEventDamageSource(),GetTriggerUnit(),GetEventDamage()) then
set isFired=true
call sl.copyList(this.s)
endif
set this=this.nextx
endloop
if sl.prev==sl then
return false
endif
loop
exitwhen this==0
if sl.isStringExists(this.word) and this.fireLocalTrig(GetEventDamageSource(),GetTriggerUnit(),GetEventDamage()) then
call sl.copyList(this.s)
endif
set this=this.nextx
endloop
return false
endmethod
endstruct
private function IsAttack takes nothing returns boolean
return FireCondition(GetEventDamageSource(),GetTriggerUnit()) and Field.fireFieldTrig()
endfunction
private function Init takes nothing returns nothing
call Damage_RegisterEvent(DamageTrig)
call TriggerAddCondition(DamageTrig,Condition(function IsAttack))
endfunction
module AEH
private static trigger trig
private static Field wordF
static boolean AEH_autoDestroy=true
unit attacker
unit target
real damage
private method destroy takes nothing returns nothing
static if thistype.AEH_onDestroy.exists then
call this.AEH_onDestroy()
endif
endmethod
private static method AEHEvent takes nothing returns boolean
local thistype this
local boolean boo=false
static if thistype.AEH_filter.exists then
if AEH_filter(DamageSource,DamagedUnit,EventDamage) then
set this=thistype.allocate()
set this.attacker=DamageSource
set this.target=DamagedUnit
set this.damage=EventDamage
set boo=this.AEH_onCreate()
if thistype.AEH_autoDestroy then
call this.destroy()
endif
endif
else
set this=thistype.allocate()
set this.attacker=DamageSource
set this.target=DamagedUnit
set this.damage=EventDamage
set boo=this.AEH_onCreate()
if thistype.AEH_autoDestroy then
call this.destroy()
endif
endif
return boo
endmethod
static method AEH_setCompatible takes string w returns nothing
call thistype.wordF.setTrue(w)
endmethod
static method AEH_setTypePriority takes string w, integer p returns nothing
set thistype.wordF=Field.setFieldPriority(w,p)
endmethod
static method AEH_register takes string w returns nothing
set thistype.trig=CreateTrigger()
call TriggerAddCondition(thistype.trig,Condition(function thistype.AEHEvent))
set thistype.wordF=Field.addTrig(thistype.trig,w)
endmethod
endmodule
endlibrary
Related Link : Damage
Demo Map (Please replace the updated code above to demo map) includes Mana Burn and Lifesteal item.
Mana Burn will override Lifesteal, so Lifesteal will not be triggered when the unit has Mana Burn.
History :
- v1.0.4
- Optimized loop.
- v1.0.3
- First Release