- Joined
- Jul 10, 2007
- Messages
- 6,306
[System]Corpse Manager
being rewritten to increase efficiency
being rewritten to increase efficiency
JASS:
native UnitAlive takes unit id returns boolean
library CorpseManager initializer Initialization uses PlayerTracker, Recycle, GenericData
/*Information
//===================================================================
Name: Unit Decaying
Version: 7.2
Author: Nestharus
Settings:
*///===================================================================
globals
private constant real UNIT_DECAY = 90
endglobals
//! textmacro CorpseManager_EXTRA_PLAYERS
//call TriggerRegisterPlayerUnitEvent(decay, GetPlayer(15), EVENT_PLAYER_UNIT_DEATH, startDecay)
//! endtextmacro
//! textmacro CorpseManager_DECAY
return not IsUnitType(u, UNIT_TYPE_HERO)
//! endtextmacro
/*//===================================================================
Description:
What does it do-
This allows you to do things when a unit decays. The normal
UnitSuspendDecay function does not work properly as it is
capped out at 8 seconds. This one works to any amount you want.
It can also change whether or not units and unit types do or don't
decay in real time.
Requirements: PlayerTracker- hiveworkshop.com/forums/jass-functions-413/system-pt-player-tracking-142554/
Recycle- thehelper.net/forums/showthread.php?t=136087
GenericData- thehelper.net/forums/showthread.php?t=141695
Installation: Advanced -> Gameplay Constants -> Corpse Decay Times -> 9999999
Settings:
------------------------------------------------------------------
UNIT_DECAY
Refers to the global decay time for all units. This is only used
if a unit does not have a set decay time.
CorpseManager_EXTRA_PLAYERS-
Refers to other players that this system runs for. Does not go
through a loop. Players 0-11 are automatically registered.
CorpseManager_DECAY-
Will check this for decay. Heroes do not decay in a normal game,
so they are automatically included.
API:
------------------------------------------------------------------
All Decay Events Evaluate The Triggers. Use TriggerAddCondition() instead
of TriggerAddAction() if you want your stuff to run.
-SetUnitDecay(unit, time)
Will set the decay time of a specific unit. Setting the time to
0 will make it default to the unitType time.
-SetUnitTypeDecay(unitType, time)
Will set the decay time of a unit type. Setting the time to 0
will make it default to the global decay time.
-SetUnitDecayFlag(unit, doesDecay)
This will make it so that the unit's flag will override the unit
type flag if enabled is true.
-SetUnitTypeDecayFlag(unit, doesDecay)
This will change the decay flag for all units of a type
-TriggerRegisterDecayEvent(trigger) returns integer
Will fire whenever a unit decays. The integer returned is
an id that can be used to unregister the trigger when desired.
-TriggerRegisterUnitDecayEvent(trigger, unit) returns integer
Will fire when the specific unit decays. The integer returned
is an id that can be used to unregister the trigger when desired.
After the unit decays, all triggers registered with the unit are
automatically unregistered, so there are no leaks.
-TriggerRegisterPlayerDecayEvent(trigger, playerId) returns integer
Will fire whenever a unit owned by player decays. The integer returned is
an id that can be used to unregister the trigger when desired.
-TriggerRegisterUnitTypeDecayEvent(trigger, unitType) returns integer
Will fire whenever a unit of unitType decays. The integer returned is
an id that can be used to unregister the trigger when desired.
-TriggerRegisterPlayerUnitTypeDecayEvent(trigger, playerId, unitType) returns integer
Will fire whenever a unit of unitType owned by player decays. The integer returned
is an id that can be used to unregister the trigger when desired.
-TriggerRemoveDecayEvent(id)
Will unregister the trigger associated with the id from the system.
-TriggerRemoveUnitDecayEvent(id, unit)
Will unregister the trigger associated with the id from the system.
Requires unit as the trigger was registered only for a specific
unit.
-TriggerRemovePlayerDecayEvent(id, playerId)
Will unregister the trigger associated with the id from the system.
Requires playerId as the trigger was registered only for a specific
player.
-TriggerRemovePlayerUnitTypeDecayEvent(id, playerId, unitTypeId)
Will unregister the trigger associated with the id from the system.
Requires playerId and unitTypeId.
-TriggerRemoveUnitTypeDecayEvent(id, unitTypeId)
Will unregister the trigger associated with the id from the system.
Reguires a unit type id as the trigger was registered only for a
specific unit type.
-GetLastDecayedUnit()
Will return the last decaying unit
-GetUnitRemainingDecayTime(unit)
Returns the remaining decay time of a unit. Will return 0
if that unit is alive. Only works on units that do decay.
-GetUnitElapsedDecayTime(unit)
Returns the elapsed decay time of a unit. Will return 0 if that
unit is alive. Only works on units that do decay.
-GetUnitDecayMaxTime(unit)
Returns the decay time of a unit. If the decay time is 0, will
return the decay time of the unit's type id. If that is 0, it
will return UNIT_DECAY.
-SetUnitRemainingDecay(unit, time)
Will set the remaining decay of a unit. A time of 0 will work here.
-CreateUnitCorpse(player, unitTypeId, x, y, facing, time)
Will create a decaying corpse. If the time is 0, it will default
to unitTypeId values. If those are 0, it will default to UNIT_DECAY.
------------------------------------------------------------------*/
private keyword CorpseUnit
private struct CorpseTimer extends array
implement PermanentId
public CorpseUnit decayUnit
public timer decayTimer
endstruct
private struct CorpseUnitType extends array
implement PermanentId
public real decay
public boolean flag
endstruct
private struct CorpseUnit extends array
implement DynamicId
public CorpseTimer decayTimer
public unit decayUnit
public real decay
public boolean flag
public integer decayHandleId
endstruct
private struct EventPlayerUnit
public static integer count = 0
public static hashtable decayEvent = InitHashtable()
endstruct
private struct EventPlayerType
public static integer array count[16]
public static hashtable decayEvent = InitHashtable()
endstruct
private struct EventUnit
public static integer count = 0
public static hashtable decayEvent = InitHashtable()
endstruct
private struct EventUnitType
public static integer count = 0
public static hashtable decayEvent = InitHashtable()
endstruct
private struct EventDecay
public static integer count = 0
public static trigger array decayEvent
endstruct
globals
private trigger decayTrig = CreateTrigger()
//Event Vars
private unit lastDecayedUnit = null
private boolexpr boolFunc
private CorpseTimer curTimer
private CorpseUnitType curUnitType
private CorpseUnit curUnit
private integer handleId
private timer runTimer
private unit runUnit
private real decayTime
private integer runUnitType
private integer runIndex
private integer runPlayerId
endglobals
private function DoesDecay takes unit u returns boolean
//! runtextmacro CorpseManager_DECAY()
endfunction
function SetUnitDecayFlag takes unit u, boolean flag returns nothing
set CorpseUnit(CorpseUnit[GetHandleId(u)]).flag = not flag
endfunction
function SetUnitTypeDecayFlag takes integer unitTypeId, boolean flag returns nothing
set CorpseUnitType(CorpseUnitType[unitTypeId]).flag = not flag
endfunction
function GetUnitRemainingDecayTime takes unit u returns real
if DoesDecay(u) and not UnitAlive(u) then
return TimerGetRemaining(CorpseUnit(CorpseUnit[GetHandleId(u)]).decayTimer.decayTimer)
endif
return 0.
endfunction
function GetUnitElapsedDecayTime takes unit u returns real
if DoesDecay(u) and not UnitAlive(u) then
return TimerGetElapsed(CorpseUnit(CorpseUnit[GetHandleId(u)]).decayTimer.decayTimer)
endif
return 0.
endfunction
function GetUnitDecayMaxTime takes unit u returns real
if DoesDecay(u) then
set curUnit = CorpseUnit[GetHandleId(u)]
set curUnitType = CorpseUnitType[GetUnitTypeId(u)]
if not (curUnit.flag and curUnitType.flag) then
if curUnit.decay > 0 then
return curUnit.decay
elseif curUnitType.decay > 0 then
return curUnitType.decay
endif
return UNIT_DECAY
endif
endif
return 0.
endfunction
function SetUnitDecay takes unit u, real decayTime returns nothing
set handleId = GetHandleId(u)
set curUnit = CorpseUnit[handleId]
set curUnit.decayHandleId = handleId
set curUnit.decay = decayTime
endfunction
function SetUnitTypeDecay takes integer unitTypeId, real decayTime returns nothing
set CorpseUnitType(CorpseUnitType[unitTypeId]).decay = decayTime
endfunction
constant function GetLastDecayedUnit takes nothing returns unit
return lastDecayedUnit
endfunction
function TriggerRegisterUnitDecayEvent takes trigger t, unit u returns integer
call SaveTriggerHandle(EventUnit.decayEvent, GetHandleId(u), EventUnit.count, t)
set EventUnit.count = EventUnit.count + 1
return EventUnit.count
endfunction
function TriggerRegisterDecayEvent takes trigger t returns integer
set EventDecay.decayEvent[EventDecay.count] = t
set EventDecay.count = EventDecay.count + 1
return EventDecay.count
endfunction
function TriggerRegisterPlayerDecayEvent takes trigger t, integer playerId returns integer
call SaveTriggerHandle(EventPlayerUnit.decayEvent, playerId, EventPlayerUnit.count, t)
set EventPlayerUnit.count = EventPlayerUnit.count + 1
return EventPlayerUnit.count
endfunction
function TriggerRegisterUnitTypeDecayEvent takes trigger t, integer unitTypeId returns integer
call SaveTriggerHandle(EventUnitType.decayEvent, unitTypeId, EventUnitType.count, t)
set EventUnitType.count = EventUnitType.count + 1
return EventUnitType.count
endfunction
function TriggerRegisterPlayerUnitTypeDecayEvent takes trigger t, integer playerId, integer unitTypeId returns integer
call SaveTriggerHandle(EventPlayerType.decayEvent, unitTypeId, playerId+16*EventPlayerType.count[playerId], t)
set EventPlayerType.count[playerId] = EventPlayerType.count[playerId] + 1
return EventUnitType.count
endfunction
function TriggerRemoveUnitDecayEvent takes integer id, unit u returns nothing
set EventUnit.count = EventUnit.count - 1
set handleId = GetHandleId(u)
call SaveTriggerHandle(EventUnit.decayEvent, handleId, id, LoadTriggerHandle(EventUnit.decayEvent, handleId, EventUnit.count))
endfunction
function TriggerRemoveDecayEvent takes integer id returns nothing
set EventDecay.count = EventDecay.count + -1
set EventDecay.decayEvent[id] = EventDecay.decayEvent[EventDecay.count]
endfunction
function TriggerRemovePlayerDecayEvent takes integer id, integer playerId returns nothing
set EventPlayerUnit.count = EventPlayerUnit.count - 1
call SaveTriggerHandle(EventPlayerUnit.decayEvent, playerId, id, LoadTriggerHandle(EventPlayerUnit.decayEvent, playerId, EventPlayerUnit.count))
endfunction
function TriggerRemoveUnitTypeDecayEvent takes integer id, integer unitTypeId returns nothing
set EventUnitType.count = EventUnitType.count - 1
call SaveTriggerHandle(EventUnitType.decayEvent, unitTypeId, id, LoadTriggerHandle(EventUnitType.decayEvent, unitTypeId, EventUnitType.count))
endfunction
function TriggerRemovePlayerUnitTypeDecayEvent takes integer id, integer playerId, integer unitTypeId returns nothing
set EventPlayerType.count[playerId] = EventPlayerType.count[playerId] - 1
call SaveTriggerHandle(EventPlayerType.decayEvent, unitTypeId, playerId+16*id, LoadTriggerHandle(EventPlayerType.decayEvent, unitTypeId, playerId+16*EventPlayerType.count[playerId]))
endfunction
private function EndDecay takes nothing returns nothing
set runTimer = GetExpiredTimer()
set curTimer = CorpseTimer[GetHandleId(runTimer)]
set curUnit = curTimer.decayUnit
set runUnitType = GetUnitTypeId(curUnit.decayUnit)
if runUnitType > 0 and not UnitAlive(curUnit.decayUnit) and not (curUnit.flag and curUnitType.flag) then
set lastDecayedUnit = curUnit.decayUnit
//all
set runIndex = EventDecay.count
loop
exitwhen runIndex == 0
set runIndex = runIndex - 1
call TriggerEvaluate(EventDecay.decayEvent[runIndex])
endloop
//unit
set runIndex = EventUnit.count
set handleId = GetHandleId(curUnit.decayUnit)
loop
exitwhen runIndex == 0
set runIndex = runIndex - 1
call TriggerEvaluate(LoadTriggerHandle(EventUnit.decayEvent, handleId, runIndex))
endloop
call FlushChildHashtable(EventUnit.decayEvent, handleId)
set EventUnit.count = 0
//unit type
set runIndex = EventUnitType.count
loop
exitwhen runIndex == 0
set runIndex = runIndex - 1
call TriggerEvaluate(LoadTriggerHandle(EventUnitType.decayEvent, runUnitType, runIndex))
endloop
//player unit
set runPlayerId = GetPlayerId(GetOwningPlayer(curUnit.decayUnit))
set runIndex = EventPlayerUnit.count
loop
exitwhen runIndex == 0
set runIndex = runIndex - 1
call TriggerEvaluate(LoadTriggerHandle(EventPlayerUnit.decayEvent, runPlayerId, runIndex))
endloop
//player unit type
set runIndex = EventPlayerType.count[runPlayerId]
loop
exitwhen runIndex == 0
set runIndex = runIndex - 1
call TriggerEvaluate(LoadTriggerHandle(EventPlayerType.decayEvent, runPlayerId+16*runIndex, runIndex))
endloop
call RemoveUnit(lastDecayedUnit)
endif
set curUnit.decayTimer = 0
set curUnit.decay = 0
set curUnit.flag = false
call CorpseUnit.release(curUnit.decayHandleId)
endfunction
function SetUnitRemainingDecay takes unit u, real time returns nothing
if DoesDecay(u) and not UnitAlive(u) then
call TimerStart(CorpseUnit(CorpseUnit[GetHandleId(u)]).decayTimer.decayTimer, time, false, function EndDecay)
endif
endfunction
function CreateUnitCorpse takes player p, integer unitTypeId, real x, real y, real facing, real time returns unit
set runTimer = Timer.get()
set curTimer = CorpseTimer[GetHandleId(runTimer)]
set curTimer.decayTimer = runTimer
set runUnit = CreateCorpse(p, unitTypeId, x, y, facing)
set handleId = GetHandleId(runUnit)
set curUnit = CorpseUnit[handleId]
set curUnit.decayUnit = runUnit
set curTimer.decayUnit = curUnit
set curUnit.decayTimer = curTimer
set curUnit.decayHandleId = handleId
if time > 0 then
set curUnit.decay = time
call TimerStart(runTimer, curUnit.decay, false, function EndDecay)
elseif not curUnitType.flag then
set curUnitType = CorpseUnitType[GetUnitTypeId(runUnit)]
if curUnitType.decay > 0 then
call TimerStart(runTimer, curUnitType.decay, false, function EndDecay)
else
call TimerStart(runTimer, UNIT_DECAY, false, function EndDecay)
endif
debug else
debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Made a unit that does not decay!")
endif
return runUnit
endfunction
private function StartDecay takes nothing returns boolean
set runUnit = GetTriggerUnit()
if DoesDecay(runUnit) then
set handleId = GetHandleId(runUnit)
set curUnit = CorpseUnit[handleId]
set curUnit.decayHandleId = handleId
set curUnitType = CorpseUnitType[GetUnitTypeId(runUnit)]
if not (curUnit.flag and curUnitType.flag) then
if curUnit.decay > 0 then
set decayTime = curUnit.decay
elseif curUnitType.decay > 0 then
set decayTime = curUnitType.decay
else
set decayTime = UNIT_DECAY
endif
if curUnit.decayTimer == 0 then
set runTimer = Timer.get()
set curTimer = CorpseTimer[GetHandleId(runTimer)]
set curTimer.decayUnit = curUnit
set curTimer.decayTimer = runTimer
set curUnit.decayTimer = curTimer
set curUnit.decayUnit = runUnit
endif
call TimerStart(curUnit.decayTimer.decayTimer, decayTime, false, function EndDecay)
endif
endif
return false
endfunction
private function Initialization takes nothing returns nothing
local integer x = 11
set boolFunc = Condition(function StartDecay)
call TriggerAddCondition(decayTrig, boolFunc)
loop
set x = x - 1
call TriggerRegisterPlayerUnitEvent(decayTrig, GetPlayer(x), EVENT_PLAYER_UNIT_DEATH, null)
exitwhen x == 0
endloop
//! runtextmacro CorpseManager_EXTRA_PLAYERS()
endfunction
endlibrary
JASS:
scope Test initializer Initialization
globals
private constant integer unitTypeId = 'hpea'
private constant real unitTypeDecayTime = 1
private trigger tStart = CreateTrigger()
private event e = TriggerRegisterTimerEvent(tStart, 0, false)
private trigger t = CreateTrigger()
private real x
private real y
endglobals
private function Test takes nothing returns boolean
local unit u = CreateUnit(Player(0), unitTypeId, GetUnitX(GetLastDecayedUnit()), GetUnitY(GetLastDecayedUnit()), 0)
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, GetUnitName(GetLastDecayedUnit()) + " has decayed")
call KillUnit(u)
set u = null
return false
endfunction
private function Start takes nothing returns boolean
local unit u
set x = GetRectCenterX(bj_mapInitialPlayableArea)
set y = GetRectCenterY(bj_mapInitialPlayableArea)
set u = CreateUnit(Player(0), unitTypeId, x, y, 0)
set u = CreateUnit(Player(0), unitTypeId, x, y, 0)
call TriggerAddCondition(t, Condition(function Test))
call PanCameraTo(x, y)
call SetUnitTypeDecay(unitTypeId, unitTypeDecayTime)
call KillUnit(u)
set u = null
call TriggerRegisterUnitTypeDecayEvent(t, unitTypeId)
return false
endfunction
private function Initialization takes nothing returns nothing
call TriggerAddCondition(tStart, Condition(function Start))
endfunction
endscope
Last edited: