library RuneSystem initializer init
globals
// You can specify the max amount of Items/SpawnLocs each struct can have.
// The number shouldn't be too big, otherwise it will cause errors.
private constant integer MAX_RUNES = 10
// How often the periodic event fires.
private constant real CHECK_INTERVAL = 0.05
endglobals
// END OF USER CONFIG!
globals
private item array Rune
private hashtable Hash
endglobals
private interface RuneFace
method onSpawn takes nothing returns nothing defaults nothing
method onPickup takes nothing returns nothing defaults nothing
method onPeriodic takes nothing returns nothing defaults nothing
method onItemDestroy takes nothing returns nothing defaults nothing
endinterface
struct Runes extends RuneFace
private integer RuneCount
private integer SpawnCount
private integer array Items[MAX_RUNES]
private rect array SpawnLoc[MAX_RUNES]
static unit TriggerUnit
static item TriggerRune
static method create takes nothing returns Runes
local Runes this = Runes.allocate()
set this.RuneCount = 0
set this.SpawnCount = 0
return this
endmethod
method add takes integer rune returns nothing
static if DEBUG_MODE then
if HaveSavedInteger(Hash, rune, this) then
debug call BJDebugMsg("ERROR: Adding an same item twice is not possible!")
return
endif
endif
set this.Items[this.RuneCount] = rune
set this.RuneCount = this.RuneCount + 1
call SaveInteger(Hash, rune, this, this.RuneCount)
endmethod
method remove takes integer rune returns nothing
local integer pos = LoadInteger(Hash, rune, this)
local integer i = pos
local boolean witem = false
loop
exitwhen i >= this.RuneCount
static if DEBUG_MODE then
if LoadInteger(Hash, this.Items[i], this) == 0 then
debug call BJDebugMsg("ERROR: Cannot remove an item that hasn't been added!")
set witem = true
exitwhen witem
endif
endif
set this.Items[i] = this.Items[i+1]
call SaveInteger(Hash, this.Items[i], this, i)
set i = i + 1
endloop
if not witem then
set this.RuneCount = this.RuneCount - 1
endif
endmethod
method addSpawn takes rect r returns nothing
static if DEBUG_MODE then
if HaveSavedInteger(Hash, GetHandleId(r), this) then
call BJDebugMsg("ERROR: Cannot add the same rect twice.")
return
endif
endif
set this.SpawnLoc[this.SpawnCount] = r
set this.SpawnCount = this.SpawnCount + 1
call SaveInteger(Hash, GetHandleId(r), this, this.SpawnCount)
endmethod
method removeSpawn takes rect r returns nothing
local integer pos = LoadInteger(Hash, GetHandleId(r), this)
local integer i = pos
local boolean wrect = false
loop
exitwhen i >= pos
static if DEBUG_MODE then
if LoadInteger(Hash, GetHandleId(this.SpawnLoc[i]), this) == 0 then
debug call BJDebugMsg("ERROR: Cannot remove an rect that hasn't been added!")
set wrect = true
exitwhen wrect
endif
endif
set this.SpawnLoc[i] = this.SpawnLoc[i+1]
call SaveInteger(Hash, GetHandleId(this.SpawnLoc[i]), this, i)
set i = i + 1
endloop
if not wrect then
set this.SpawnCount = this.SpawnCount - 1
endif
endmethod
method list takes nothing returns nothing
local integer i = 0
local item rune
loop
exitwhen i > this.RuneCount
set rune = CreateItem(this.Items[i], 0, 0)
call BJDebugMsg("Item Name in Pos " + I2S(LoadInteger(Hash, this.Items[i], this)) + ": " + GetItemName(rune))
call RemoveItem(rune)
set i = i + 1
endloop
set rune = null
endmethod
method spawnList takes nothing returns nothing
local integer i = 0
loop
exitwhen i > this.SpawnCount
call BJDebugMsg("X of Rect in Pos " + I2S(LoadInteger(Hash, GetHandleId(this.SpawnLoc[i]), this)) + ": " + I2S(R2I(GetRectCenterX(this.SpawnLoc[i]))))
call BJDebugMsg("Y of Rect in Pos " + I2S(LoadInteger(Hash, GetHandleId(this.SpawnLoc[i]), this)) + ": " + I2S(R2I(GetRectCenterY(this.SpawnLoc[i]))))
set i = i + 1
endloop
endmethod
method startTimer takes real interval returns nothing
local timer t = CreateTimer()
local timer c = CreateTimer()
call SaveInteger(Hash, GetHandleId(t), 0, this)
call SaveInteger(Hash, GetHandleId(c), 0, this)
call TimerStart(t, interval, true, function thistype.createRune)
call TimerStart(c, CHECK_INTERVAL, true, function thistype.check)
set t = null
set c = null
endmethod
private static method createRune takes nothing returns nothing
local Runes this = LoadInteger(Hash, GetHandleId(GetExpiredTimer()), 0)
local integer i = GetRandomInt(0, this.SpawnCount-1)
if Rune[this] == null then
set Rune[this] = CreateItem(this.Items[GetRandomInt(0, this.RuneCount-1)], GetRectCenterX(this.SpawnLoc[i]), GetRectCenterY(this.SpawnLoc[i]))
call SaveInteger(Hash, GetHandleId(Rune[this]), 0, this)
set this.TriggerRune = Rune[this]
call this.onSpawn()
endif
endmethod
private static method check takes nothing returns nothing
local Runes this = LoadInteger(Hash, GetHandleId(GetExpiredTimer()), 0)
set this.TriggerRune = Rune[this]
if Rune[this] != null then
call this.onPeriodic()
endif
if GetWidgetLife(Rune[this]) < 0.405 and not (Rune[this] == null) then
call this.onItemDestroy()
set Rune[this] = null
endif
endmethod
endstruct
function InitRunes takes nothing returns Runes
return Runes.create()
endfunction
function AddRune takes Runes d, integer rune returns nothing
call d.add(rune)
endfunction
function RemoveRune takes Runes d, integer rune returns nothing
call d.remove(rune)
endfunction
function AddSpawn takes Runes d, rect r returns nothing
call d.addSpawn(r)
endfunction
function RemoveSpawn takes Runes d, rect r returns nothing
call d.removeSpawn(r)
endfunction
function StartRuneTimer takes Runes d, real interval returns nothing
call d.startTimer(interval)
endfunction
function ListRunes takes Runes d returns nothing
call d.list()
endfunction
function ListSpawns takes Runes d returns nothing
call d.spawnList()
endfunction
private function Pickup takes nothing returns boolean
local item pRune = GetManipulatedItem()
local Runes data = LoadInteger(Hash, GetHandleId(pRune), 0)
if GetManipulatedItem() == Rune[data] then
set data.TriggerUnit = GetTriggerUnit()
set data.TriggerRune = pRune
call data.onPickup()
set Rune[data] = null
endif
return true
endfunction
private function init takes nothing returns nothing
local trigger detectpickup = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(detectpickup, EVENT_PLAYER_UNIT_PICKUP_ITEM)
call TriggerAddCondition(detectpickup, Condition(function Pickup))
set Hash = InitHashtable()
set detectpickup = null
endfunction
endlibrary