- Joined
- Apr 30, 2011
- Messages
- 359
JASS:
//========================================================================================
//
// Trigger Stack
// -*- overcold_ice -*-
//
// -[*] Requirements:
// - JNGP
// - latest version of JassHelper
//
// -[*] Optional Requirements:
// - /*New*/ Table hiveworkshop.com/forums/showthread.php?t=188084
//
// For your advanced trigger 'variable'
// This system provides easier and optimized 'advanced' trigger variable type.
// Doesn't support any TriggerSleepAction/PolledWait.
//
// -[*] API:
//
// type triggerstack extends integer
// type triggerstackaction extends integer
//
// function TSRegNullEvent takes nothing returns triggerstack
// registers a new no-event trigger
//
// function TSReg$EVENT$Event takes $REQUIRED_ARGUMENTS$ returns triggerstack
// $EVENT$ -> TriggerRegister$EVENT$ (from natives)
// ex: TriggerRegisterDeathEvent
// -> TSRegDeathEvent
// ex: TriggerRegisterEnterRegion
// -> TSRegEnterRegionEvent (add "Event" in this case)
// $REQUIRED_ARGUMENTS$ -> its arguments other than trigger,
// in that same order
//
// function TSUnregEvent takes triggerstack ts returns nothing
// unregisters a triggerstack (destroys it in other word)
//
// function TSAddAction takes triggerstack ts, code c returns triggerstackaction
// adds an action (actually, condition) to the triggerstack
//
// function TSRemoveAction takes triggerstack ts, triggerstackaction tsa returns nothing
// removes an action from the triggerstack
//
// function TSEnable takes triggerstack ts, boolean enabled returns nothing
// enable if enabled = true, or disable it (just like ordinary trigger's
// enable/disable)
//
// function TSIsEnabled takes triggerstack ts returns boolean
// return true if the triggerstack is enabled, otherwise false
//
// function TSExecute takes triggerstack ts returns nothing
// execute a triggerstack, ignoring whether the triggerstack is enabled
// or disabled
//
// -[*] Required Example:
/*
// . . .
local triggerstack ts1 = TSRegNullEvent()
local triggerstack ts2 = TSRegPlayerUnitEvent(Player(0), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
local triggerstackaction a1 = TSAddAction(ts1, function.onEffect2)
local triggerstackaction a2 = TSAddAction(ts2, function.onEffect1)
if TSIsEnabled(ts1) then
call TSEnable(ts1, false)
endif
// . . .
*/
//========================================================================================
library TriggerStack requires optional /*New*/Table
type triggerstack extends integer
type triggerstackaction extends integer
globals
private integer tsc = 0
private integer tstc = 0
private integer tsac = 0
private key tsins
private key tstrg
private key tsevn
private key tsact
private key tsenb
private key lln
private key llp
private key lll
private key tscon
private key tscow
private constant string B = "B"
private constant string H = "H"
private constant string R = "R"
private constant string S = "S"
endglobals
static if LIBRARY_Table then
private module TableInit
private static method onInit takes nothing returns nothing
set .t = TableArray [51]
endmethod
endmodule
endif
private struct T extends array
static if LIBRARY_Table then
static TableArray t
implement TableInit
else
static hashtable t = InitHashtable()
endif
endstruct
private function TriggerStackAction takes nothing returns boolean
local integer i = GetHandleId(GetTriggeringTrigger())
local integer l
local trigger t = CreateTrigger()
static if LIBRARY_Table then
set i = T.t [tsins] [i]
set l = T.t [lll] [i]
else
set i = LoadInteger(T.t, tsins, i)
set l = LoadInteger(T.t, lll, i)
endif
loop
exitwhen l == 0
static if LIBRARY_Table then
if T.t [tsenb].boolean [l] then
call TriggerAddCondition(t, T.t [tsact].boolexpr [l])
call TriggerEvaluate(t)
call TriggerClearConditions(t)
endif
else
if LoadBoolean(T.t, tsenb, l) then
call TriggerAddCondition(t, LoadBoolexprHandle(T.t, tsact, l))
call TriggerEvaluate(t)
call TriggerClearConditions(t)
endif
endif
static if LIBRARY_Table then
set i = T.t [llp] [l]
else
set i = LoadInteger(T.t, llp, l)
endif
endloop
call DestroyTrigger(t)
set t = null
return false
endfunction
private function TriggerStackCreate takes nothing returns integer
local integer this
static if LIBRARY_Table then
set this = T.t [lll] [0]
else
set this = LoadInteger(T.t, lll, 0)
endif
if this == 0 then
set tstc = tstc + 1
set this = tstc
else
static if LIBRARY_Table then
set T.t [lll] [0] = T.t [lll] [this]
call T.t [lll].remove(this)
else
call SaveInteger(T.t, lll, 0, LoadInteger(T.t, lll, this))
call RemoveSavedInteger(T.t, lll, this)
endif
endif
static if LIBRARY_Table then
set T.t [tstrg].trigger [this] = CreateTrigger()
set T.t [tsins] [GetHandleId(T.t [tstrg].trigger [this])] = this
call TriggerAddCondition(T.t [tstrg].trigger [this], Condition(function TriggerStackAction))
else
call SaveTriggerHandle(T.t, tstrg, this, CreateTrigger())
call SaveInteger(T.t, tsins, GetHandleId(LoadTriggerHandle(T.t, tstrg, this)), this)
call TriggerAddCondition(LoadTriggerHandle(T.t, tstrg, this), Condition(function TriggerStackAction))
endif
return this
endfunction
private function TriggerStackDestroy takes integer this returns nothing
static if LIBRARY_Table then
set T.t [lll] [this] = T.t [lll] [0]
set T.t [lll] [0] = this
call TriggerClearConditions(T.t [tstrg].trigger [this])
call DestroyTrigger(T.t [tstrg].trigger [this])
call T.t [tsins].remove(GetHandleId(T.t [tstrg].trigger [this]))
call T.t [tstrg].handle.remove(this)
else
call SaveInteger(T.t, lll, this, LoadInteger(T.t, lll, 0)
call SaveInteger(T.t, lll, 0, this)
call TriggerClearConditions(LoadTriggerHandle(T.t, tstrg, this)
call DestroyTrigger(LoadTriggerHandle(T.t, tstrg, this))
call RemoveSavedInteger(T.t, tsins, GetHandleId(LoadTriggerHandle(T.t, tstrg, this)))
call RemoveSavedHandle(T.t, tstrg, this)
endif
endfunction
private function TriggerStackAdd takes integer ts returns integer
local integer this
static if LIBRARY_Table then
set this = T.t [lln] [0]
else
set this = LoadInteger(T.t, lln, 0)
endif
if this == 0 then
set tsc = tsc + 1
set this = tsc
else
static if LIBRARY_Table then
set T.t [lln] [0] = T.t [lln] [this]
else
call SaveInteger(T.t, lln, 0, LoadInteger(T.t, lln, this)
endif
endif
static if LIBRARY_Table then
if T.t [lll] [ts] == 0 then
set T.t [lll] [ts] = -ts
endif
set T.t [llp] [this] = T.t [lll] [ts]
set T.t [lln] [this] = -ts
set T.t [lln] [T.t [lll] [ts]] = this
set T.t [lll] [ts] = this
else
if LoadInteger(T.t, lll, ts) == 0 then
call SaveInteger(T.t, lll, ts, -ts)
endif
call SaveInteger(T.t, llp, this, LoadInteger(T.t, lll, ts))
call SaveInteger(T.t, lln, this, -ts)
call SaveInteger(T.t, lln, LoadInteger(T.t, lll, ts), this)
call SaveInteger(T.t, lll, ts, this)
endif
return this
endfunction
private function TriggerStackRemove takes integer ts, integer this returns nothing
static if LIBRARY_Table then
if T.t [lln] [this] == -ts then
if T.t [llp] [this] == -ts then
call TriggerStackDestroy(ts)
else
set T.t [lll] [ts] = T.t [llp] [this]
set T.t [lln] [T.t [llp] [this]] = -ts
endif
else
set T.t [lln] [T.t [llp] [this]] = T.t [lln] [this]
set T.t [llp] [T.t [lln] [this]] = T.t [llp] [this]
endif
call T.t [llp].remove(this)
set T.t [lln] [this] = T.t [lln] [0]
set T.t [lln] [0] = this
else
if LoadInteger(T.t, lln, this) == -ts then
if LoadInteger(T.t, llp, this) == -ts then
call TriggerStackDestroy(ts)
else
call SaveInteger(T.t, lll, ts, LoadInteger(T.t, llp, this))
call SaveInteger(T.t, lln, LoadInteger(T.t, llp, this), -ts)
endif
else
call SaveInteger(T.t, lln, LoadInteger(T.t, llp, this), LoadInteger(T.t, lln, this))
call SaveInteger(T.t, llp, LoadInteger(T.t, lln, this), LoadInteger(T.t, llp, this))
endif
call RemoveInteger(T.t, llp, this)
call SaveInteger(T.t, lln, this, LoadInteger(T.t, lln, 0))
call SaveInteger(T.t, lln, 0, this)
endif
endfunction
private function PrivConv_B2S takes boolean b returns string
if b then
return "0"
else
return "1"
endif
endfunction
globals
private integer tsNull
endglobals
function TSRegNullEvent takes nothing returns triggerstack
local integer ts
if tsNull == 0 then
set tsNull = TriggerStackCreate()
endif
set ts = TriggerStackAdd(tsNull)
static if LIBRARY_Table then
set T.t [tsevn] [ts] = tsNull
else
call SaveInteger(T.t, tsevn, i, tsNull)
endif
return ts
endfunction
function TSUnregEvent takes triggerstack ts returns nothing
static if LIBRARY_Table then
call TriggerStackRemove(T.t [tsevn] [ts], ts)
else
call TriggerStackRemove(LoadInteger(T.t, tsevn, ts), ts)
endif
endfunction
//! textmacro TriggerStack___MakeRegAPI takes NAME, FUNCARG, CONVERSION, REGFUNC, REGARG
globals
private key ts$NAME$
endglobals
function TSReg$NAME$Event takes $FUNCARG$ returns triggerstack
local integer i = $CONVERSION$
local integer ts
static if LIBRARY_Table then
if T.t [ts$NAME$] [i] == 0 then
set T.t [ts$NAME$] [i] = TriggerStackCreate()
endif
set ts = TriggerStackAdd(T.t [ts$NAME$] [i])
set T.t [tsevn] [ts] = T.t [ts$NAME$] [i]
call TriggerRegister$REGFUNC$(T.t [tstrg].trigger [ts], $REGARG$)
return ts
else
if LoadInteger(T.t, ts$NAME$, i) == 0 then
call SaveInteger(T.t, ts$NAME$, i, TriggerStackCreate())
endif
set ts = TriggerStackAdd(LoadInteger(T.t, ts$NAME$, i))
call SaveInteger(T.t, tsevn, i, LoadInteger(T.t, ts$NAME$, i))
call TriggerRegister$REGFUNC$(LoadTriggerHandle(T.t, tstrg, ts), $REGARG$)
return ts
endif
endfunction
//! endtextmacro
//! runtextmacro TriggerStack___MakeRegAPI("Death", "widget w", "GetHandleId(w)", "DeathEvent", "w")
//! runtextmacro TriggerStack___MakeRegAPI("DialogButton", "button b", "GetHandleId(b)", "DialogButtonEvent", "b")
//! runtextmacro TriggerStack___MakeRegAPI("Dialog", "dialog d", "GetHandleId(d)", "DialogEvent", "d")
//! runtextmacro TriggerStack___MakeRegAPI("EnterRegion", "region r, boolexpr f", "StringHash(H + I2S(GetHandleId(r)) + H + I2S(GetHandleId(f)))", "EnterRegion", "r, f")
//! runtextmacro TriggerStack___MakeRegAPI("FilterUnit", "unit u, unitevent e, boolexpr f", "StringHash(H + I2S(GetHandleId(u)) + H + I2S(GetHandleId(e)) + H + I2S(GetHandleId(f)))", "FilterUnitEvent", "u, e, f")
//! runtextmacro TriggerStack___MakeRegAPI("Game", "gameevent e", "GetHandleId(e)", "GameEvent", "e")
//! runtextmacro TriggerStack___MakeRegAPI("GameState", "gamestate gs, limitop lt, real lv", "StringHash(H + I2S(GetHandleId(gs)) + H + I2S(GetHandleId(lt)) + R + R2S(lv))", "GameStateEvent", "gs, lt, lv")
//! runtextmacro TriggerStack___MakeRegAPI("LeaveRegion", "region r, boolexpr f", "StringHash(H + I2S(GetHandleId(r)) + H + I2S(GetHandleId(f)))", "LeaveRegion", "r, f")
//! runtextmacro TriggerStack___MakeRegAPI("PlayerAllianceChange", "player p, alliancetype at", "StringHash(H + I2S(GetHandleId(p)) + H + I2S(GetHandleId(at)))", "PlayerAllianceChange", "p, at")
//! runtextmacro TriggerStack___MakeRegAPI("PlayerChat", "player p, string s, boolean b", "StringHash(H + I2S(GetHandleId(p)) + S + I2S(StringHash(s)) + B + PrivConv_B2S(b))", "PlayerChatEvent", "p, s, b")
//! runtextmacro TriggerStack___MakeRegAPI("Player", "player p, playerevent e", "StringHash(H + I2S(GetHandleId(p)) + H + I2S(GetHandleId(e)))", "PlayerEvent", "p, e")
//! runtextmacro TriggerStack___MakeRegAPI("PlayerState", "player p, playerstate ps, limitop lt, real lv", "StringHash(H + I2S(GetHandleId(p)) + H + I2S(GetHandleId(ps)) + H + I2S(GetHandleId(lt)) + R + R2S(lv))", "PlayerStateEvent", "p, ps, lt, lv")
//! runtextmacro TriggerStack___MakeRegAPI("PlayerUnit", "player p, playerunitevent e, boolexpr f", "StringHash(H + I2S(GetHandleId(p)) + H + I2S(GetHandleId(e)) + H + I2S(GetHandleId(f)))", "PlayerUnitEvent", "p, e, f")
//! runtextmacro TriggerStack___MakeRegAPI("Timer", "real t, boolean p", "StringHash(R + R2S(t) + B + PrivConv_B2S(p))", "TimerEvent", "t, p")
//! runtextmacro TriggerStack___MakeRegAPI("TimerExpire", "timer t", "GetHandleId(t)", "TimerExpireEvent", "t")
//! runtextmacro TriggerStack___MakeRegAPI("TrackableHit", "trackable t", "GetHandleId(t)", "TrackableHitEvent", "t")
//! runtextmacro TriggerStack___MakeRegAPI("TrackableTrack", "trackable t", "GetHandleId(t)", "TrackableTrackEvent", "t")
//! runtextmacro TriggerStack___MakeRegAPI("Unit", "unit u, unitevent e", "StringHash(H + I2S(GetHandleId(u)) + H + I2S(GetHandleId(e)))", "UnitEvent", "u, e")
//! runtextmacro TriggerStack___MakeRegAPI("UnitInRange", "unit u, real r, boolexpr f", "StringHash(H + I2S(GetHandleId(u)) + R + R2S(r) + H + I2S(GetHandleId(f)))", "UnitInRange", "u, r, f")
//! runtextmacro TriggerStack___MakeRegAPI("UnitState", "unit u, unitstate us, limitop lt, real lv", "StringHash(H + I2S(GetHandleId(u)) + H + I2S(GetHandleId(us)) + H + I2S(GetHandleId(lt)) + R + R2S(lv))", "UnitStateEvent", "u, us, lt, lv")
//! runtextmacro TriggerStack___MakeRegAPI("Variable", "string vn, limitop lt, real lv", "StringHash(S + I2S(StringHash(vn)) + H + I2S(GetHandleId(lt)) + R + R2S(lv))", "VariableEvent", "vn, lt, lv")
function TSAddAction takes triggerstack ts, code c returns triggerstackaction
set tsac = tsac + 1
static if LIBRARY_Table then
set T.t [tsact].boolexpr [ts] = And(T.t [tsact].boolexpr [ts], Condition(c))
set T.t [tscon].boolexpr [tsac] = Condition(c)
set T.t [tscow] [tsac] = ts
else
call SaveBoolexprHandle(T.t, tsact, ts, And(LoadBoolexprHandle(T.t, tsact, ts), Condition(c)))
call SaveBoolexprHanlde(T.t, tscon, tsac, Condition(c))
call SaveInteger(T.t, tscow, tsac, ts)
endif
return tsac
endfunction
function TSRemoveAction takes triggerstack ts, triggerstackaction tsa returns nothing
local integer l = tsac
local boolexpr b
loop
exitwhen l == 0
static if LIBRARY_Table then
if T.t [tscow] [l] == ts and l != tsa then
set b = And(b, T.t [tscon].boolexpr [l])
endif
else
if LoadInteger(T.t, tscow, l) == ts and l != tsa then
set b = And(b, LoadBoolexprHandle(T.t, tscon, l))
endif
endif
set l = l - 1
endloop
static if LIBRARY_Table then
set T.t [tscon].boolexpr [tsa] = T.t [tscon].boolexpr [tsac]
set T.t [tscow] [tsa] = T.t [tscow] [tsac]
call T.t [tscon].handle.remove(tsa)
call T.t [tscow].remove(tsa)
else
call SaveBoolexprHandle(T.t, tscon, tsa, LoadBoolexprHandle(T.t, tscon, tsac))
call SaveInteger(T.t, tscow, tsa, LoadInteger(T.t, tscow, tsac))
call RemoveSavedHandle(T.t, tscon, tsa)
call RemoveSavedInteger(T.t, tscow, tsa)
endif
set tsac = tsac - 1
endfunction
function TSEnable takes triggerstack ts, boolean b returns nothing
static if LIBRARY_Table then
set T.t [tsenb].boolean [ts] = b
else
call SaveBoolean(T.t, tsenb, ts, b)
endif
endfunction
function TSIsEnabled takes triggerstack ts returns boolean
static if LIBRARY_Table then
return T.t [tsenb].boolean [ts]
else
return LoadBoolean(T.t, tsenb, ts)
endif
endfunction
function TSExecute takes triggerstack ts returns nothing
static if LIBRARY_Table then
call TriggerEvaluate(T.t [tstrg].trigger [ts])
else
call TriggerEvaluate(LoadTriggerHandle(T.t, tstrg, ts))
endif
endfunction
endlibrary