Nestharus
o-o
- Reaction score
- 84
Player Tracking
Host Tracking
cJASS overhaul done!
Read API to see all of the improved features and the move from indexed arrays to dequeues.
ploop was also removed.
cJASS
vJASS
Host Tracking
cJASS overhaul done!
Read API to see all of the improved features and the move from indexed arrays to dequeues.
ploop was also removed.
cJASS
JASS:
include "cj_types.j"
library PlayerManager initializer Ini {
/*===================================================================
Name: C Player Manager
Version: 3.4
Author: Nestharus
Settings:
*///===================================================================
//remove all units owned by players not in map at ini
define REMOVE_UNITS_ON_INI_FOR_INACTIVE = false
//remove all units owned by player when that player leaves, done after event fire
define REMOVE_UNITS_ON_LEAVE = false
define TRACK_HUMAN = true
define TRACK_COMPUTER = false
define TRACK_ACTIVE = false
define TRACK_INACTIVE = false
define KICK_PLAYER_ON_REMOVE = true
//fire events when a human leaves/removed
define HUMAN_OUT_EVENT = true
//fire events when a computer is removed
define COMPUTER_OUT_EVENT = false
//for use with GetHiddenPlayer
//player 14 is suggested as it has bounty etc enabled
define private HIDDEN_PLAYER_ID = 14
/*//===================================================================
Player Manager keeps track of players in linked lists for easier traversal, faster loops, and less operations.
It has 5 collections of players-
HumanPlayer
Has all active human players in the game in order
ComputerPlayer
Has all active computer players in the game in order
ActivePlayer
Has all active players in the game in order
InactivePlayer
Has all inactive players in the game in order
Players
Has all players in the game in order
All collections are kept updated through out the game except for Players as it will always contain
all players 0-15 within the game. All collections always maintain initial order.
Example- 1, 3, 5, and 8 are active human players
5 leaves
1, 3, 8 would now be in human players in that order
InactivePlayers are stored in the order of leaving players, so it's possible to see who
left first and who left last.
All functions and collections relating to specific features are only in the code if specified in settings.
For this reason, all setting definitions that relates to code that might be removed are not private.
To keep code from breaking and keep code efficient, use #if with the settings.
API-
Structs:
HumanPlayer, ComputerPlayer, ActivePlayer, InactivePlayer
Propertiers:
thistype first
First player (id)
thistype last
Last player (id)
thistype next
Next player (id)
thistype previous
Previous player (id)
player get
Get player (id). If get is null, player is not in the collection. This can happen
with id 0 a lot.
static int count
Gets the total player count
Methods:
HumanPlayer and ComputerPlayer only-
void remove()
Removes player from the game
static triggercondition addOnOut(boolexpr c)
Adds boolexpr to player out trigger and returns the triggercondition
static void removeOnOut(triggercondition c)
Removes triggercondition from player out trigger
Players
player get
Gets the player handle
bool active
Is player active?
static player lastRemoved
Stores last removed player for event response
static int lastRemovedId
Stores the id of last removed player for event response
static player getLocal
GetLocalPlayer() but faster
static player hidden
HIDDEN_PLAYER_ID
===================================================================*/
private player localPlayer
private bool isPlayerActive[]
private player lastRemovedPlayer = null
private int lastRemovedPlayerId = 0
private player players[]
private trigger humanLeaves;
define private REMOVE_PLAYER(PLAYER_TYPE, PLAYER_OUT_EVENT) = {
public void remove() {
#if KICK_PLAYER_ON_REMOVE
RemovePlayer(.get, PLAYER_GAME_RESULT_DEFEAT)
if (localPlayer == .get) {
EndGame(false)
}
#endif
REMOVE_PLAYER(PLAYER_TYPE, .get, PLAYER_OUT_EVENT)
}
}
define private PLAYER_STRUCT(PLAYER_TYPE) = {
private struct P_##PLAYER_TYPE extends array {
public static thistype first = 0
public static thistype last = 0
public static int count = 0
public player get;
public thistype next;
public thistype previous;
}//end struct P_##PLAYER_TYPE
struct PLAYER_TYPE extends array {
public player operator get() {
return P_##PLAYER_TYPE[this].get;
}//end operator getPlayer
public static thistype operator first() {
return P_##PLAYER_TYPE[this].first;
}//end static operator first
public static thistype operator last() {
return P_##PLAYER_TYPE[this].last;
}//end static operator last
public static int operator count() {
return P_##PLAYER_TYPE[this].count;
}//end static operator count
public thistype operator next() {
return P_##PLAYER_TYPE[this].next;
}//end operator next
public thistype operator previous() {
return P_##PLAYER_TYPE[this].previous;
}//end operator previous
#if PLAYER_TYPE == HumanPlayer
REMOVE_PLAYER(PLAYER_TYPE, HUMAN_OUT_EVENT)
#if HUMAN_OUT_EVENT
public static trigger out = CreateTrigger();
public static triggercondition addOnOut(boolexpr c) {return TriggerAddCondition(out, c);}
public static void removeOnOut(triggercondition c) {TriggerRemoveCondition(out, c);}
#endif
#endif
#if PLAYER_TYPE == ComputerPlayer
REMOVE_PLAYER(PLAYER_TYPE, COMPUTER_OUT_EVENT)
#if COMPUTER_OUT_EVENT
public static trigger out = CreateTrigger();
public static triggercondition addOnOut(boolexpr c) {return TriggerAddCondition(out, c);}
public static void removeOnOut(triggercondition c) {TriggerRemoveCondition(out, c);}
#endif
#endif
}//end struct Players
}//end define PLAYER_STRUCT
#if TRACK_HUMAN
PLAYER_STRUCT(HumanPlayer);
#endif
#if TRACK_COMPUTER
PLAYER_STRUCT(ComputerPlayer);
#endif
#if TRACK_ACTIVE
PLAYER_STRUCT(ActivePlayer);
#endif
#if TRACK_INACTIVE
PLAYER_STRUCT(InactivePlayer);
#endif
struct Players extends array {
public player operator get() {
return players[this]
}//end player operator get()
public bool operator active() {
return isPlayerActive[this]
}//end bool operator active
public static player operator lastRemoved() {
return lastRemovedPlayer
}//end player operator lastRemoved
public static int operator lastRemovedId() {
return lastRemovedPlayerId
}//end player operator lastRemovedId
public static player operator getLocal() {
return localPlayer
}//end player operator local
public static player operator hidden() {
return players[HIDDEN_PLAYER_ID];
}//end player operator hidden
}//end struct Players
#if REMOVE_UNITS_ON_INI_FOR_INACTIVE || REMOVE_UNITS_ON_LEAVE
private group removeUnitGroup = CreateGroup();
private boolexpr removeUnits
#endif
define private REMOVE_FROM_PLAYER_STRUCT(PLAYER_TYPE, WHICH_PLAYER_ID) = {
//decrease count
P_##PLAYER_TYPE.count--
//remove from PLAYER_TYPE struct
if (WHICH_PLAYER_ID == P_##PLAYER_TYPE.last) {
P_##PLAYER_TYPE.last = P_##PLAYER_TYPE[WHICH_PLAYER_ID].previous
}//end if
if (WHICH_PLAYER_ID == P_##PLAYER_TYPE.first) {
P_##PLAYER_TYPE.first = P_##PLAYER_TYPE[WHICH_PLAYER_ID].next
}//end elseif
P_##PLAYER_TYPE[WHICH_PLAYER_ID].next.previous = P_##PLAYER_TYPE[WHICH_PLAYER_ID].previous
P_##PLAYER_TYPE[WHICH_PLAYER_ID].previous.next = P_##PLAYER_TYPE[WHICH_PLAYER_ID].next
//set to null
P_##PLAYER_TYPE[WHICH_PLAYER_ID].get = null
}//end define REMOVE_FROM_PLAYER_STRUCT(PLAYER_TYPE, WHICH_PLAYER)
define private ADD_TO_PLAYER_STRUCT(PLAYER_TYPE, WHICH_PLAYER_ID) = {
//increase count
P_##PLAYER_TYPE.count++
//add to PLAYER_TYPE struct
P_##PLAYER_TYPE.last.next = WHICH_PLAYER_ID
P_##PLAYER_TYPE[WHICH_PLAYER_ID].previous = P_##PLAYER_TYPE.last
P_##PLAYER_TYPE.last = WHICH_PLAYER_ID
P_##PLAYER_TYPE.last.next = bj_MAX_PLAYER_SLOTS
if (P_##PLAYER_TYPE.first.get == null) {//if empty
P_##PLAYER_TYPE.first = WHICH_PLAYER_ID
P_##PLAYER_TYPE.first.previous = bj_MAX_PLAYER_SLOTS
}//if
//set the get
P_##PLAYER_TYPE[WHICH_PLAYER_ID].get = players[WHICH_PLAYER_ID]
}//end define ADD_TO_PLAYER_STRUCT
define private REMOVE_PLAYER(PLAYER_TYPE, WHICH_PLAYER, TRIGGER_CHECK) = {
//update event variables
lastRemovedPlayer = WHICH_PLAYER
lastRemovedPlayerId = GetPlayerId(lastRemovedPlayer)
if (isPlayerActive[lastRemovedPlayerId]) {//if the player is active
//remove player from specific player struct
#if PLAYER_TYPE == HumanPlayer //human
#if TRACK_HUMAN
REMOVE_FROM_PLAYER_STRUCT(PLAYER_TYPE, lastRemovedPlayerId)
#endif
#else //computer
#if TRACK_COMPUTER
REMOVE_FROM_PLAYER_STRUCT(PLAYER_TYPE, lastRemovedPlayerId)
#endif
#endif
//remove from actives
#if TRACK_ACTIVE
REMOVE_FROM_PLAYER_STRUCT(ActivePlayer, lastRemovedPlayerId)
#endif
//add to inactives
#if TRACK_INACTIVE
ADD_TO_PLAYER_STRUCT(InactivePlayer, lastRemovedPlayerId)
#endif
//set active to false
isPlayerActive[lastRemovedPlayerId] = false
//fire trigger
#if TRIGGER_CHECK
TriggerEvaluate(PLAYER_TYPE.out)
#endif
//remove units on leave
#if REMOVE_UNITS_ON_LEAVE
GroupEnumUnitsOfPlayer(removeUnitGroup, lastRemovedPlayer, removeUnits)
#endif
}//end if
}//end define REMOVE_PLAYER
private void Ini() {
int i = 0
humanLeaves = CreateTrigger()
//do ini if either REMOVE_UNITS
#if REMOVE_UNITS_ON_INI_FOR_INACTIVE || REMOVE_UNITS_ON_LEAVE
removeUnits = Condition(lambda bool() {
RemoveUnit(GetFilterUnit())
return false
})
#endif
//ini 0 through bj_MAX_PLAYERS - 1
do {
players<i> = Player(i)
if (GetPlayerSlotState(players<i>) == PLAYER_SLOT_STATE_PLAYING) then
#if TRACK_ACTIVE
ADD_TO_PLAYER_STRUCT(ActivePlayer, i)
#endif
if (GetPlayerController(players<i>) == MAP_CONTROL_USER) then
#if TRACK_HUMAN
ADD_TO_PLAYER_STRUCT(HumanPlayer, i)
if (HumanPlayer.count > 1) {
TriggerRegisterPlayerEvent(humanLeaves, players<i>, EVENT_PLAYER_LEAVE)
}//end if
#endif
#if TRACK_COMPUTER
else
ADD_TO_PLAYER_STRUCT(ComputerPlayer, i)
#endif
endif
isPlayerActive<i> = true
#if REMOVE_UNITS_ON_INI_FOR_INACTIVE || TRACK_INACTIVE
else
#if REMOVE_UNITS_ON_INI_FOR_INACTIVE
GroupEnumUnitsOfPlayer(removeUnitGroup, players<i>, removeUnits)
#endif
#if TRACK_INACTIVE
ADD_TO_PLAYER_STRUCT(InactivePlayer, i)
#endif
#endif
endif
} whilenot ++i == bj_MAX_PLAYERS
//ini bj_MAX_PLAYERS through bj_MAX_PLAYER_SLOTS-1
do {
players<i> = Player(i)
} whilenot ++i == bj_MAX_PLAYER_SLOTS
#if TRACK_HUMAN
if (HumanPlayer.count > 1) {
TriggerRegisterPlayerEvent(humanLeaves, HumanPlayer.first.get, EVENT_PLAYER_LEAVE)
TriggerAddCondition(humanLeaves, Condition(lambda bool() {
REMOVE_PLAYER(HumanPlayer, GetTriggerPlayer(), HUMAN_OUT_EVENT)
return false
}))
}//end if
else {
DestroyTrigger(humanLeaves)
humanLeaves = null
}//else
#endif
localPlayer = GetLocalPlayer()
}//end function Ini()
}
</i></i></i></i></i></i></i>
vJASS
JASS:
library PlayerTracker initializer Initialization
/*V Player Tracker
Version: 7.4
Author: Nestharus
CTRL+F =================================================================== to jump category
Settings:
*///===================================================================
globals
private constant boolean REMOVE_UNITS = false
private constant boolean REMOVE_UNITS_LEAVE = false
private constant boolean INACTIVE_PLAYER = false
private constant boolean ON_HUMAN_LEAVE = true
private constant boolean ON_COMPUTER_LEAVE = true
endglobals/*//
Description
===================================================================
Tracks human, computer, active, and inactive players through out the game and
allows you to iterate through them.
Human players are people playing the map
Computer players are computers in the map
Active Players are all players 0-11 that are in the map
Inactive Players are all players 0-11 that aren't in the map
Leaving players are moved from active to inactive etc and all the collections of players
are kept updated through the game.
For example, if you want to run AI for all computer players, you can cycle through them without having to
filter out human players. It does the indexing, cycling, and set up as fast
and efficiently as possible.
Requirements: NA
Installation: NA
Variable Settings
===================================================================
-REMOVE_UNITS
refers to whether or not units should be removed if a player is in the map.
-REMOVE_UNITS_LEAVE
refers to whether or not units should be removed if a player leaves the game
or is removed from the game by force.
-INACTIVE_PLAYER
refers to whether or not inactive players should be tracked.
-ON_HUMAN_LEAVE
will run a trigger whenever a human leaves or is removed
Allows use of OnPlayerLeave function
-ON_COMPUTER_LEAVE
will run a trigger whenever a computer leaves or is removed
Allows use of OnComputerLeave function
API
===================================================================
constant function GetHiddenPlayer takes nothing returns player
Returns player 14, which has all features (bounty etc) working. Useful for temporary
player operations where a dummy player is needed.
constant function GetHumanCount takes nothing returns integer
Returns a count of all humans. This will not return the index
for the last human player, but rather the index+1
example-
local integer i = GetHumanCount()-1
constant function GetComputerCount takes nothing returns integer
Returns a count of all computers. This will not return the index
for the last computer player, but rather the index+1
example-
local integer i = GetComputerCount()-1
constant function GetActivePlayerCount takes nothing returns integer
Returns a count of all active players. This will not return the index
for the last active player, but rather the index+1
example-
local integer i = GetActivePlayerCount()-1
constant function GetInactivePlayerCount takes nothing returns integer
Returns a count of all inactive players. This will not return the index
for the last inactive player, but rather the index+1
example-
local integer i = GetInactivePlayerCount()-1
function GetPlayer takes integer i returns player
Returns a player given an id. Exactly like the Player() native, but
slightly faster.
example-
local player p = GetPlayer(0)
function GetHuman takes integer i returns player
Returns a human player given an indexed id. The indexed ids
do not refer to the player ids and the order is not maintained.
This is used for iteration.
example-
local integer x = GetHumanCount()
loop
set x = x -1
call CreateUnit(GetHuman(x), 'hpea', 0, 0, 270) //human 0 might be player 11
exitwhen x == 0
endloop
function GetComputer takes integer i returns player
Returns a computer player given an indexed id. The indexed ids
do not refer to the player ids and the order is not maintained.
This is used for iteration.
example-
local integer x = GetComputerCount()
loop
set x = x -1
call CreateUnit(GetComputer(x), 'hpea', 0, 0, 270) //computer 0 might be player 3
exitwhen x == 0
endloop
function GetActivePlayer takes integer i returns player
Returns an active player player given an indexed id. The indexed ids
do not refer to the player ids and the order is not maintained.
This is used for iteration.
example-
local integer x = GetActivePlayerCount()
loop
set x = x -1
call CreateUnit(GetActivePlayer(x), 'hpea', 0, 0, 270) //active player 0 might be player 6
exitwhen x == 0
endloop
function GetInactivePlayer takes integer i returns player
Returns an inactive player given an indexed id. The indexed ids
do not refer to the player ids and the order is not maintained.
This is used for iteration.
example-
local integer x = GetInactivePlayerCount()
loop
set x = x -1
call CreateUnit(GetInactivePlayer(x), 'hpea', 0, 0, 270) //inactive player 0 might be player 4
exitwhen x == 0
endloop
function GetHumanId takes integer i returns integer
Returns a player id given an indexed human id. The indexed ids do
not refer to the player ids and order is not maintainted.
This is used for iteration
example-
local integer x = GetHumanCount()
loop
set x = x -1
call DisplayTextToPlayer(GetLocalHuman(), 0, 0, I2S(GetHumanId(x)))
exitwhen x == 0
endloop
function GetComputerId takes integer i returns integer
Returns a player id given an indexed computer id. The indexed ids do
not refer to the player ids and order is not maintainted.
This is used for iteration
example-
local integer x = GetComputerCount()
loop
set x = x -1
call DisplayTextToPlayer(GetLocalHuman(), 0, 0, I2S(GetComputerId(x)))
exitwhen x == 0
endloop
function GetActivePlayerId takes integer i returns integer
Returns a player id given an indexed active player id. The indexed ids do
not refer to the player ids and order is not maintainted.
This is used for iteration
example-
local integer x = GetActivePlayerCount()
loop
set x = x -1
call DisplayTextToPlayer(GetLocalHuman(), 0, 0, I2S(GetActivePlayerId(x)))
exitwhen x == 0
endloop
function GetInactivePlayerId takes integer i returns integer
Returns a player id given an indexed inactive player id. The indexed ids do
not refer to the player ids and order is not maintainted.
This is used for iteration
example-
local integer x = GetInactivePlayerCount()
loop
set x = x -1
call DisplayTextToPlayer(GetLocalHuman(), 0, 0, I2S(GetInactivePlayerId(x)))
exitwhen x == 0
endloop
function IsPlayerActive takes integer i returns boolean
Checks to see whether or not a player is active given a player id
function IsPlayerInactive takes integer i returns boolean
Checks to see whether or not a player is inactive given a player id
function OnHumanLeave takes boolexpr onLeaveCode returns triggercondition
Runs code whenever a human is removed or leaves the game.
function RemoveOnHumanLeave takes triggercondition c returns nothing
Removes code to be run when a human leaves.
function OnComputerLeave takes boolexpr onLeaveCode returns triggercondition
Runs code whenever a computer is removed.
function RemoveOnComputerLeave takes triggercondition c returns nothing
Removes code to be run when a computer leaves.
function RemoveHuman takes player playerToRemove returns nothing
Forcefully deactivates a human player. Will not remove that player from the game.
function RemoveComputer takes player playerToRemove returns nothing
Forcefully deactivates a computer player. Computer players can't be removed from the game.
constant function GetRemovedPlayer takes nothing returns player
Gets the last removed player
constant function GetLocalHuman takes nothing returns player
Exactly like GetLocalPlayer() but slightly faster.
===================================================================*/
globals
private constant integer PLAYER_SLOT_COUNT = 12
private constant integer SLOT_COUNT = 16
private constant integer SLOT_START = 0
private constant integer PLAYER_COUNT = 11
private constant integer EXT_PLAYER_COUNT = 15
private constant integer HIDDEN_PLAYER_ID = 14
private player array human[PLAYER_SLOT_COUNT]
private integer array humanId[PLAYER_SLOT_COUNT]
private integer array humanIndex[PLAYER_SLOT_COUNT]
private integer array humanIndexed[PLAYER_SLOT_COUNT]
private integer humanCount = SLOT_START
private player array computer[PLAYER_SLOT_COUNT]
private integer array computerId[PLAYER_SLOT_COUNT]
private integer array computerIndex[PLAYER_SLOT_COUNT]
private integer array computerIndexed[PLAYER_SLOT_COUNT]
private integer computerCount = SLOT_START
private player array allPlayers[SLOT_COUNT]
private integer allPlayersCount = SLOT_START
private player array activePlayer[PLAYER_SLOT_COUNT]
private integer array activePlayerId[PLAYER_SLOT_COUNT]
private integer array activePlayerIndex[PLAYER_SLOT_COUNT]
private integer array activePlayerIndexed[PLAYER_SLOT_COUNT]
private integer activePlayerCount = SLOT_START
private player array inactivePlayer[SLOT_COUNT]
private integer array inactivePlayerId[SLOT_COUNT]
private integer inactivePlayerCount = SLOT_START
private boolean array isInactivePlayer[PLAYER_SLOT_COUNT]
private player localPlayer
private trigger humanLeaves = CreateTrigger()
private trigger onHumanLeave
private trigger onComputerLeave
private group removeUnitGroup
private boolexpr removeUnits
private integer i
private player curPlayer
private integer curPlayerId
endglobals
constant function GetRemovedPlayer takes nothing returns player
return curPlayer
endfunction
constant function GetLocalHuman takes nothing returns player
return localPlayer
endfunction
constant function GetHiddenPlayer takes nothing returns player
return allPlayers[HIDDEN_PLAYER_ID]
endfunction
constant function GetHumanCount takes nothing returns integer
return humanCount
endfunction
constant function GetComputerCount takes nothing returns integer
return computerCount
endfunction
constant function GetActivePlayerCount takes nothing returns integer
return activePlayerCount
endfunction
constant function GetInactivePlayerCount takes nothing returns integer
return inactivePlayerCount
endfunction
function GetPlayer takes integer i returns player
static if DEBUG_MODE then
if i < 0 or i > EXT_PLAYER_COUNT then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "PlayerTracker Error: Player ID out of bounds!")
return null
endif
endif
return allPlayers<i>
endfunction
function GetHuman takes integer i returns player
static if DEBUG_MODE then
if i < 0 or i >= humanCount then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "PlayerTracker Error: Human Index Value out of bounds!")
return null
endif
endif
return human[humanIndexed<i>]
endfunction
function GetComputer takes integer i returns player
static if DEBUG_MODE then
if i < 0 or i >= computerCount then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "PlayerTracker Error: Computer Index Value out of bounds!")
return null
endif
endif
return computer[computerIndexed<i>]
endfunction
function GetActivePlayer takes integer i returns player
static if DEBUG_MODE then
if i < 0 or i >= activePlayerCount then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "PlayerTracker Error: Active Player Index Value out of bounds!")
return null
endif
endif
return activePlayer[activePlayerIndexed<i>]
endfunction
function GetInactivePlayer takes integer i returns player
static if DEBUG_MODE then
if i < 0 or i >= inactivePlayerCount then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "PlayerTracker Error: Inactive Player Index Value out of bounds!")
return null
endif
endif
return inactivePlayer<i>
endfunction
function GetHumanId takes integer i returns integer
static if DEBUG_MODE then
if i < 0 or i >= humanCount then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "PlayerTracker Error: Human Index Value out of bounds!")
return 0
endif
endif
return humanId[humanIndexed<i>]
endfunction
function GetComputerId takes integer i returns integer
static if DEBUG_MODE then
if i < 0 or i >= computerCount then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "PlayerTracker Error: Computer Index Value out of bounds!")
return 0
endif
endif
return computerId[computerIndexed<i>]
endfunction
function GetActivePlayerId takes integer i returns integer
static if DEBUG_MODE then
if i < 0 or i >= activePlayerCount then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "PlayerTracker Error: Active Player Index Value out of bounds!")
return 0
endif
endif
return activePlayerId[activePlayerIndexed<i>]
endfunction
function GetInactivePlayerId takes integer i returns integer
static if DEBUG_MODE then
if i < 0 or i >= inactivePlayerCount then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "PlayerTracker Error: Inactive Player Index Value out of bounds!")
return 0
endif
endif
return inactivePlayerId<i>
endfunction
function RemoveOnHumanLeave takes triggercondition c returns nothing
static if ON_HUMAN_LEAVE then
call TriggerRemoveCondition(onHumanLeave, c)
endif
endfunction
function RemoveOnComputerLeave takes triggercondition c returns nothing
static if ON_COMPUTER_LEAVE then
call TriggerRemoveCondition(onComputerLeave, c)
endif
endfunction
function OnHumanLeave takes boolexpr onLeaveCode returns triggercondition
static if ON_HUMAN_LEAVE then
static if DEBUG_MODE then
if onLeaveCode == null then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "PlayerTracker Error: Invalid On Leave Code!")
return null
endif
endif
return TriggerAddCondition(onHumanLeave, onLeaveCode)
else
return null
endif
endfunction
function OnComputerLeave takes boolexpr onLeaveCode returns triggercondition
static if ON_COMPUTER_LEAVE then
static if DEBUG_MODE then
if onLeaveCode == null then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "PlayerTracker Error: Invalid On Leave Code!")
return null
endif
endif
return TriggerAddCondition(onComputerLeave, onLeaveCode)
else
return null
endif
endfunction
function IsPlayerActive takes integer i returns boolean
static if DEBUG_MODE then
if i < 0 or i > EXT_PLAYER_COUNT then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "PlayerTracker Error: Player Index Value out of bounds!")
return false
endif
endif
return not isInactivePlayer<i>
endfunction
function IsPlayerInactive takes integer i returns boolean
static if DEBUG_MODE then
if i < 0 or i > EXT_PLAYER_COUNT then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "PlayerTracker Error: Player Index Value out of bounds!")
return false
endif
endif
return isInactivePlayer<i>
endfunction
private function RemoveUnits takes nothing returns boolean
call RemoveUnit(GetFilterUnit())
return false
endfunction
function RemoveHuman takes player playerToRemove returns nothing
static if DEBUG_MODE then
if playerToRemove == null or humanCount == 0 then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "You either have no humans left to remove or you passed in a null player!")
return
endif
endif
set curPlayer = playerToRemove
set curPlayerId = GetPlayerId(curPlayer)
set humanCount = humanCount - 1
set activePlayerCount = activePlayerCount - 1
if humanIndex[curPlayerId] <= humanCount then
set humanIndexed[humanIndex[curPlayerId]] = humanCount
set humanIndex[humanId[humanCount]] = humanIndex[curPlayerId]
endif
if activePlayerIndex[curPlayerId] <= activePlayerCount then
set activePlayerIndexed[activePlayerIndex[curPlayerId]] = activePlayerCount
set activePlayerIndex[activePlayerId[activePlayerCount]] = activePlayerIndex[curPlayerId]
endif
set isInactivePlayer[curPlayerId] = true
static if INACTIVE_PLAYER then
set inactivePlayer[inactivePlayerCount] = allPlayers<i>
set inactivePlayerId[inactivePlayerCount] = i
set inactivePlayerCount = inactivePlayerCount + 1
endif
static if ON_HUMAN_LEAVE then
call TriggerEvaluate(onHumanLeave)
endif
static if REMOVE_UNITS_LEAVE then
call GroupEnumUnitsOfPlayer(removeUnitGroup, curPlayer, removeUnits)
endif
endfunction
function RemoveComputer takes player playerToRemove returns nothing
static if DEBUG_MODE then
if playerToRemove == null or computerCount == 0 then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "You either have no computers left to remove or you passed in a null player!")
return
endif
endif
set curPlayer = playerToRemove
set curPlayerId = GetPlayerId(curPlayer)
set computerCount = computerCount - 1
set activePlayerCount = activePlayerCount - 1
if computerIndex[curPlayerId] < computerCount then
set computerIndexed[computerIndex[curPlayerId]] = computerCount
set computerIndex[computerId[computerCount]] = computerIndex[curPlayerId]
endif
if activePlayerIndex[curPlayerId] <= activePlayerCount then
set activePlayerIndexed[activePlayerIndex[curPlayerId]] = activePlayerCount
set activePlayerIndex[activePlayerId[activePlayerCount]] = activePlayerIndex[curPlayerId]
endif
set isInactivePlayer[curPlayerId] = true
static if INACTIVE_PLAYER then
set inactivePlayer[inactivePlayerCount] = allPlayers<i>
set inactivePlayerId[inactivePlayerCount] = i
set inactivePlayerCount = inactivePlayerCount + 1
endif
static if ON_COMPUTER_LEAVE then
call TriggerEvaluate(onComputerLeave)
endif
static if REMOVE_UNITS_LEAVE then
call GroupEnumUnitsOfPlayer(removeUnitGroup, curPlayer, removeUnits)
endif
endfunction
private function HumanLeaves takes nothing returns boolean
set curPlayer = GetTriggerPlayer()
set curPlayerId = GetPlayerId(curPlayer)
if not isInactivePlayer[curPlayerId] then
set humanCount = humanCount - 1
set activePlayerCount = activePlayerCount - 1
if humanIndex[curPlayerId] <= humanCount then
set humanIndexed[humanIndex[curPlayerId]] = humanCount
set humanIndex[humanId[humanCount]] = humanIndex[curPlayerId]
endif
if activePlayerIndex[curPlayerId] <= activePlayerCount then
set activePlayerIndexed[activePlayerIndex[curPlayerId]] = activePlayerCount
set activePlayerIndex[activePlayerId[activePlayerCount]] = activePlayerIndex[curPlayerId]
endif
set isInactivePlayer[curPlayerId] = true
static if INACTIVE_PLAYER then
set inactivePlayer[inactivePlayerCount] = allPlayers<i>
set inactivePlayerId[inactivePlayerCount] = i
set inactivePlayerCount = inactivePlayerCount + 1
endif
static if ON_HUMAN_LEAVE then
call TriggerEvaluate(onHumanLeave)
endif
static if REMOVE_UNITS_LEAVE then
call GroupEnumUnitsOfPlayer(removeUnitGroup, curPlayer, removeUnits)
endif
endif
return false
endfunction
private function Initialization takes nothing returns nothing
static if ON_HUMAN_LEAVE then
set onHumanLeave = CreateTrigger()
endif
static if ON_COMPUTER_LEAVE then
set onComputerLeave = CreateTrigger()
endif
static if REMOVE_UNITS then
set removeUnitGroup = CreateGroup()
elseif REMOVE_UNITS_LEAVE then
set removeUnitGroup = CreateGroup()
endif
set i = EXT_PLAYER_COUNT
static if REMOVE_UNITS then
set removeUnits = Condition(function RemoveUnits)
else
static if REMOVE_UNITS_LEAVE then
set removeUnits = Condition(function RemoveUnits)
endif
endif
loop
set allPlayers<i> = Player(i)
set i = i - 1
exitwhen i == PLAYER_COUNT
endloop
loop
set allPlayers<i> = Player(i)
if GetPlayerSlotState(allPlayers<i>) == PLAYER_SLOT_STATE_PLAYING then
set activePlayerIndex<i> = activePlayerCount
set activePlayerIndexed[activePlayerCount] = activePlayerCount
set activePlayer[activePlayerCount] = allPlayers<i>
set activePlayerId[activePlayerCount] = i
if GetPlayerController(activePlayer[activePlayerCount]) == MAP_CONTROL_USER then
set humanIndex<i> = humanCount
set humanIndexed[humanCount] = humanCount
set human[humanCount] = activePlayer[activePlayerCount]
set humanId[humanCount] = i
if humanCount != 0 then
call TriggerRegisterPlayerEvent(humanLeaves, human[humanCount], EVENT_PLAYER_LEAVE)
endif
set humanCount = humanCount + 1
else
set computerIndex<i> = computerCount
set computerIndexed[computerCount] = computerCount
set computer[computerCount] = activePlayer[activePlayerCount]
set computerId[computerCount] = i
set computerCount = computerCount + 1
endif
set activePlayerCount = activePlayerCount + 1
else
set isInactivePlayer<i> = true
static if REMOVE_UNITS then
call GroupEnumUnitsOfPlayer(removeUnitGroup, allPlayers<i>, removeUnits)
endif
static if INACTIVE_PLAYER then
set inactivePlayer[inactivePlayerCount] = allPlayers<i>
set inactivePlayerId[inactivePlayerCount] = i
set inactivePlayerCount = inactivePlayerCount + 1
endif
endif
exitwhen i == 0
set i = i - 1
endloop
if humanCount > 1 then
call TriggerRegisterPlayerEvent(humanLeaves, human[0], EVENT_PLAYER_LEAVE)
call TriggerAddCondition(humanLeaves, Condition(function HumanLeaves))
else
call DestroyTrigger(humanLeaves)
endif
set humanLeaves = null
set localPlayer = GetLocalPlayer()
endfunction
endlibrary
</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>