library AdvancedTreeReviveSystem /* v1.0.0.0, created by DeathChef
struct ReviveTrees extends array
Description
Dead tree indexes are mixed up and randomized
Indexes are only checked a repeated time when all other current existing indexes are checked
Prevents the same tree from being checked "5 times in a row" when there are other trees in
the queue unlike other systems
Fields
trigger ReviveTrees
- Disable to stop dying trees from being queued to revive
- Re enable to let dying trees queue to be revived
readonly static boolean Paused
- Is Timer Paused
Methods
static method RegisterTreeDeath takes destructable d returns nothing
- Newly created trees don't get revived, so
I made a method to manually add them
static method TimerPauseAuto takes nothing returns nothing
- If paused it unpauses/if unpaused it pauses
- Stops dead trees from being revived
static method TimerPauseBoolean takes boolean flag returns nothing
static method TimerPause takes nothing returns nothing
static method TimerResume takes nothing returns nothing
Settings
*/
//! textmacro ATR_SETTINGS
private static constant boolean REVIVE_IS_INITIALY_ON = true
//On map initialization Reviving is initialy on
private static constant boolean STORING_IS_INITIALY_ON = true
//On map initialization storing fallen trees are on
private static constant integer TREE_TYPE = 'LTlt'
//Add more types here and to the CONDITIONS module
private static constant rect TREE_REGISTER_AREA = bj_mapInitialPlayableArea
//In this rect area only trees on init will get revived
private static constant real CHECK_RATE = .34
//How often Check priodically runs
private static real UnitCheckDistance = 151
//Distance a tree will be disallowed by a unit
private static real CheckRatio = .34
//Chance to check per tree loop check
//Must be >= 0 and <= 1
//! endtextmacro
/*
Conditions
*/
//! textmacro ATR_CONDITIONS
local integer DestTypeId = GetDestructableTypeId(GetFilterDestructable())
return DestTypeId == TREE_TYPE// or DestTypeId == CONSTANT
//Can add more destructable types here
//! endtextmacro
/*
*/
struct ReviveTrees extends array
//! runtextmacro ATR_SETTINGS()
readonly static boolean Paused
private static timer CheckTimer
private static integer DeadTreesCount = 0
private static destructable array DeadTrees
//Recycle indexes
//(Currently checking true or false side)
private static boolean IsTrue = true
//(Indicates what boolean side it it on)
private static boolean array IsCheckedAsTrue
//(Count for each boolean side)
private static integer CheckedTrueCount = 0
private static integer CheckedFalseCount = 0
//(Boolean index -> actual index)
private static integer array CheckedTrue
private static integer array CheckedFalse
//(Actual index -> boolean index)
private static integer array CheckedTrueIndex
private static integer array CheckedFalseIndex
//
private static method IsUnitDead takes nothing returns boolean
return not IsUnitType(GetFilterUnit(), UNIT_TYPE_DEAD)
endmethod
private static method Count takes nothing returns nothing
set bj_groupCountUnits = bj_groupCountUnits + 1
endmethod
private static method CheckPath takes nothing returns nothing
local group UnitsInRange
local integer Index
local integer TreeBeingChecked
local integer Temp_MaxIndex = DeadTreesCount
loop
exitwhen Temp_MaxIndex == 0
if GetRandomReal(0., 1.) < CheckRatio then
if IsTrue then
set Index = GetRandomInt(1, CheckedTrueCount)
set TreeBeingChecked = CheckedTrue[Index]
if Index < CheckedTrueCount then
set CheckedTrue[Index] = CheckedTrue[CheckedTrueCount]
set CheckedTrueIndex[CheckedTrue[CheckedTrueCount]] = Index
elseif CheckedTrueCount == 1 then
set IsTrue = false
endif
set CheckedTrueCount = CheckedTrueCount - 1
set CheckedFalseCount = CheckedFalseCount + 1
set CheckedFalse[CheckedFalseCount] = TreeBeingChecked
set IsCheckedAsTrue[TreeBeingChecked] = false
set CheckedFalseIndex[TreeBeingChecked] = CheckedFalseCount
else
set Index = GetRandomInt(1, CheckedFalseCount)
set TreeBeingChecked = CheckedFalse[Index]
if Index < CheckedFalseCount then
set CheckedFalse[Index] = CheckedFalse[CheckedFalseCount]
set CheckedFalseIndex[CheckedFalse[CheckedFalseCount]] = Index
elseif CheckedFalseCount == 1 then
set IsTrue = true
endif
set CheckedFalseCount = CheckedFalseCount - 1
set CheckedTrueCount = CheckedTrueCount + 1
set CheckedTrue[CheckedTrueCount] = TreeBeingChecked
set IsCheckedAsTrue[TreeBeingChecked] = true
set CheckedTrueIndex[TreeBeingChecked] = CheckedTrueCount
endif
set UnitsInRange = CreateGroup()
call GroupEnumUnitsInRange(UnitsInRange, GetDestructableX(DeadTrees[TreeBeingChecked]), GetDestructableY(DeadTrees[TreeBeingChecked]), UnitCheckDistance, CheckIsUnitDead)
set bj_groupCountUnits = 0
call ForGroup(UnitsInRange, function thistype.Count)
call DestroyGroup(UnitsInRange)
if bj_groupCountUnits == 0 then
call DestructableRestoreLife(DeadTrees[TreeBeingChecked], GetDestructableMaxLife(DeadTrees[TreeBeingChecked]), true)
if IsCheckedAsTrue[TreeBeingChecked] then
set Index = CheckedTrueIndex[TreeBeingChecked]
if Index < CheckedTrueCount then
set CheckedTrue[Index] = CheckedTrue[CheckedTrueCount]
set CheckedTrueIndex[CheckedTrue[CheckedTrueCount]] = Index
elseif CheckedTrueCount == 1 then
set IsTrue = false
endif
set CheckedTrueCount = CheckedTrueCount - 1
else
set Index = CheckedFalseIndex[TreeBeingChecked]
if Index < CheckedFalseCount then
set CheckedFalse[Index] = CheckedFalse[CheckedFalseCount]
set CheckedFalseIndex[CheckedFalse[CheckedFalseCount]] = Index
elseif CheckedFalseCount == 1 then
set IsTrue = true
endif
set CheckedFalseCount = CheckedFalseCount - 1
endif
//--
if TreeBeingChecked == DeadTreesCount then
set DeadTrees[TreeBeingChecked] = null
else
set DeadTrees[TreeBeingChecked] = DeadTrees[DeadTreesCount]
set DeadTrees[DeadTreesCount] = null
endif
if IsCheckedAsTrue[DeadTreesCount] then
set Index = CheckedTrueIndex[DeadTreesCount]
set CheckedTrue[Index] = TreeBeingChecked
set CheckedTrueIndex[TreeBeingChecked] = Index
set IsCheckedAsTrue[TreeBeingChecked] = true
else
set Index = CheckedFalseIndex[DeadTreesCount]
set CheckedFalse[Index] = TreeBeingChecked
set CheckedFalseIndex[TreeBeingChecked] = Index
set IsCheckedAsTrue[TreeBeingChecked] = false
endif
set DeadTreesCount = DeadTreesCount - 1
endif
endif
set Temp_MaxIndex = Temp_MaxIndex - 1
endloop
if DeadTreesCount == 0 then
call DestroyTimer(CheckTimer)
set CheckTimer = null
endif
endmethod
private static method TreeDies takes nothing returns nothing
set DeadTreesCount = DeadTreesCount + 1
set DeadTrees[DeadTreesCount] = GetTriggerDestructable()
if GetRandomInt(0, 1) == 0 then
set CheckedTrueCount = CheckedTrueCount + 1
set CheckedTrue[CheckedTrueCount] = DeadTreesCount
set IsCheckedAsTrue[DeadTreesCount] = true
set CheckedTrueIndex[DeadTreesCount] = CheckedTrueCount
if DeadTreesCount == 1 then
set IsTrue = true
set CheckTimer = CreateTimer()
call TimerStart(CheckTimer, CHECK_RATE, true, function thistype.CheckPath)
endif
else
set CheckedFalseCount = CheckedFalseCount + 1
set CheckedFalse[CheckedFalseCount] = DeadTreesCount
set IsCheckedAsTrue[DeadTreesCount] = false
set CheckedFalseIndex[DeadTreesCount] = CheckedFalseCount
if DeadTreesCount == 1 then
set IsTrue = false
set CheckTimer = CreateTimer()
call TimerStart(CheckTimer, CHECK_RATE, true, function thistype.CheckPath)
endif
endif
endmethod
//different methods to pause/resume this system to revive trees
static method TimerPauseAuto takes nothing returns nothing
if Paused then
if DeadTreesCount > 0 and CheckTimer != null then
set Paused = false
set CheckTimer = CreateTimer()
call TimerStart(CheckTimer, CHECK_RATE, true, function thistype.CheckPath)
endif
else
set Paused = true
call DestroyTimer(CheckTimer)
set CheckTimer = null
endif
endmethod
static method TimerPauseBoolean takes boolean flag returns nothing
if flag then
if Paused and DeadTreesCount > 0 and CheckTimer != null then
set Paused = false
set CheckTimer = CreateTimer()
call TimerStart(CheckTimer, CHECK_RATE, true, function thistype.CheckPath)
endif
else
if not Paused then
set Paused = true
call DestroyTimer(CheckTimer)
set CheckTimer = null
endif
endif
endmethod
static method TimerPause takes nothing returns nothing
if not Paused then
set Paused = true
call DestroyTimer(CheckTimer)
set CheckTimer = null
endif
endmethod
static method TimerResume takes nothing returns nothing
if Paused and DeadTreesCount > 0 and CheckTimer != null then
set Paused = false
set CheckTimer = CreateTimer()
call TimerStart(CheckTimer, CHECK_RATE, true, function thistype.CheckPath)
endif
endmethod
static trigger ReviveTrees
private static boolexpr CheckIsUnitDead
static method RegisterTreeDeath takes destructable d returns nothing
call TriggerRegisterDeathEvent(ReviveTrees, d)
endmethod
private static method IsTree takes nothing returns boolean
//! runtextmacro ATR_CONDITIONS()
endmethod
private static method RegisterTree takes nothing returns nothing
call TriggerRegisterDeathEvent(ReviveTrees, GetEnumDestructable())
endmethod
private static method onInit takes nothing returns nothing
set ReviveTrees = CreateTrigger()
call TriggerAddAction(ReviveTrees, function thistype.TreeDies)
call EnumDestructablesInRect(TREE_REGISTER_AREA, Condition(function thistype.IsTree), function thistype.RegisterTree)
call RemoveRect(TREE_REGISTER_AREA)
set CheckIsUnitDead = Condition(function thistype.IsUnitDead)
endmethod
endstruct
endlibrary