library ZoneBasedIncome initializer Init
globals
private timer incomeTimer = CreateTimer()
private group unitGroupA = CreateGroup()
private group unitGroupB = CreateGroup()
private player filterPlayer
private integer groupCounter
private IncomeZone array Zone
private integer ZoneCount = 0
endglobals
struct IncomeZone
private player mOwner = null
private integer incomeBase
private region zoneRegion = null
private rect zoneRect = null
private integer array unitsOfPlayer [16]
// static members:
private static hashtable reftable = InitHashtable()
private static trigger enterZone = CreateTrigger()
private static trigger leaveZone = CreateTrigger()
private static trigger onDeath = CreateTrigger()
static method operator [] takes region r returns thistype
return LoadInteger(reftable, GetHandleId(r), 0)
endmethod
// utility methods for zone ownership:
// @ IsOwned - returns true if the zone is owned by a player
// @ SetOwner - sets the owner of the zone
// @ GetOwner - returns the owner of the zone
// @ ClearOwner - removes the presence of an owner
method IsOwned takes nothing returns boolean
return (mOwner != null)
endmethod
method SetOwner takes player p returns nothing
set mOwner = p
endmethod
method GetOwner takes nothing returns player
return mOwner
endmethod
method ClearOwner takes nothing returns nothing
set mOwner = null
endmethod
// getter for region/rect members:
// accesses the region/rect members of the IncomeZone.
method GetRegion takes nothing returns region
return zoneRegion
endmethod
method GetRect takes nothing returns rect
return zoneRect
endmethod
// GiveIncome:
// adds the specified income to the owning player's gold pool
method GiveIncome takes nothing returns nothing
if (IsOwned()) then
call SetPlayerState(mOwner, PLAYER_STATE_RESOURCE_GOLD, /*
*/ GetPlayerState(mOwner, PLAYER_STATE_RESOURCE_GOLD) + incomeBase)
endif
endmethod
// GetPlayerWithMostUnits
// returns the player's id with the most amount of units in the zone
//
// if the player with the most units has the same amount of units as
// someone else then returns -1. this covers the situation where the
// most units any player has in that zone is 0.
method GetPlayerWithMostUnits takes nothing returns integer
local integer i = 0
local integer m = 0
loop
exitwhen (i == 16)
if ((i != m) and (unitsOfPlayer[i] > unitsOfPlayer[m])) then
set m = i
endif
set i = i + 1
endloop
loop
set i = i - 1
if ((i != m) and (unitsOfPlayer[m] == unitsOfPlayer[i])) then
return -1
endif
exitwhen (i == 0)
endloop
return m
endmethod
// CalculateOwner:
// calculates the player that should be in control of the zone
// based on the player with the most units in the zone
//
// if there is no "highest" amount of units (two players are tied)
// then it becomes idle, owned by no one, otherwise that player
// is returned
//
// the owner is set to the calculated value
private method CalculateOwner takes nothing returns nothing
local integer owner = GetPlayerWithMostUnits()
if (owner != -1) then
call SetOwner(Player(owner))
else
call ClearOwner()
endif
endmethod
// constructor:
// creates a zone with a rect and an income base to be given to
// owning players. the rect is converted to a region and registered to
// a trigger for enter/leave events.
static method create takes rect zoneRect, integer incomeBase returns thistype
local thistype zone = allocate()
set zone.zoneRect = zoneRect
set zone.zoneRegion = CreateRegion()
call RegionAddRect(zone.zoneRegion, zoneRect)
call TriggerRegisterEnterRegion(enterZone, zone.zoneRegion, null)
call TriggerRegisterLeaveRegion(enterZone, zone.zoneRegion, null)
set zone.incomeBase = incomeBase
call SaveInteger(reftable, GetHandleId(zone.zoneRegion), 0, zone)
set Zone[ZoneCount] = zone
set ZoneCount = ZoneCount + 1
return zone
endmethod
// onEnterZone()
// executes whenever a unit enters a defined zone
private static method onEnterZone takes nothing returns nothing
local IncomeZone entered
local integer playerId
local integer owner
if (not IsUnitType(GetTriggerUnit(), UNIT_TYPE_DEAD)) then
set entered = IncomeZone[GetTriggeringRegion()]
set playerId = GetPlayerId(GetOwningPlayer(GetTriggerUnit()))
set entered.unitsOfPlayer[playerId] = entered.unitsOfPlayer[playerId] + 1
call entered.CalculateOwner()
endif
endmethod
// onLeaveZone()
// executes whenever a unit leaves the zone
private static method onLeaveZone takes nothing returns nothing
local IncomeZone leaving
local integer playerId
local integer owner
if (not IsUnitType(GetTriggerUnit(), UNIT_TYPE_DEAD)) then
set leaving = IncomeZone[GetTriggeringRegion()]
set playerId = GetPlayerId(GetOwningPlayer(GetTriggerUnit()))
set leaving.unitsOfPlayer[playerId] = leaving.unitsOfPlayer[playerId] - 1
call leaving.CalculateOwner()
endif
endmethod
// onUnitDeath:
// i hope this doesn't cause too much overhead when units are dying
// in the region because it has to loop through the array of zones
// to determine if the unit is contained in any of them
private static method onUnitDeath takes nothing returns nothing
local integer i = 0
local integer owner
local unit trigunit = GetTriggerUnit()
loop
exitwhen (i == ZoneCount)
if (IsUnitInRegion(Zone[i].GetRegion(), trigunit)) then
// reduce the count of units owned by the owning player by one
set Zone[i].unitsOfPlayer[GetPlayerId(GetOwningPlayer(trigunit))] = /*
*/ Zone[i].unitsOfPlayer[GetPlayerId(GetOwningPlayer(trigunit))] - 1
// calculate new owner of the zone
call Zone[i].CalculateOwner()
endif
set i = i + 1 // loop through zones
endloop
set trigunit = null
endmethod
// initializer method:
// initializes components
private static method onInit takes nothing returns nothing
call TriggerRegisterAnyUnitEventBJ(onDeath, EVENT_PLAYER_UNIT_DEATH)
call TriggerAddAction(onDeath, function thistype.onUnitDeath)
call TriggerAddAction(enterZone, function thistype.onEnterZone)
call TriggerAddAction(leaveZone, function thistype.onLeaveZone)
endmethod
endstruct
// function OnIncome
// executes every timer interval to generate income for players
// who are controlling zones.
//
// the control of each zone is based on the algorithms in the
// IncomeZone struct which determine who actually owns the zone
// in certain situations
private function OnIncome takes nothing returns nothing
local integer i = 0 // loop through array of zones
loop
exitwhen (i == ZoneCount)
if (Zone[i].IsOwned()) then
call Zone[i].GiveIncome()
endif
set i = i + 1
endloop
endfunction
// initialization:
// initializes the income timer
private function Init takes nothing returns nothing
call IncomeZone.create(gg_rct_Region_000, 5)
call IncomeZone.create(gg_rct_Region_001, 5)
call IncomeZone.create(gg_rct_Region_002, 5)
call IncomeZone.create(gg_rct_Region_003, 5)
call TimerStart(incomeTimer, 1, true, function OnIncome)
endfunction
endlibrary