Created
August 23, 2010 19:05
-
-
Save kimoto/546095 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Name: auto team balance plugin | |
// History: | |
// ver0.3: | |
// refactoring: | |
// cleanup source code | |
// ver0.2: | |
// make base routines | |
// ver0.1: | |
// first edit | |
// | |
#include <sourcemod> | |
#include <adt_array> | |
#define PLUGIN_VERSION "0.1" | |
#define TEAM_SPECTATE 1 | |
#define TEAM_SURVIVOR 2 | |
#define TEAM_INFECTED 3 | |
#define MIN_PLAYER_SIZE 0 | |
#define MAX_PLAYER_SIZE 32 | |
#define PLUGIN_FILENAME "autoteambalance" | |
#define ARRAY_SIZE 50 | |
#define ESCAPE_LOOP_COUNT 20 | |
new Handle:g_hEnable = INVALID_HANDLE; | |
new Handle:g_hDebug = INVALID_HANDLE; | |
new Handle:g_hSelectKey = INVALID_HANDLE; | |
new bool:g_bEnable = true; | |
new bool:g_bDebug = true; | |
new g_iSelectKey = 0; | |
public Plugin:myinfo = | |
{ | |
name = "auto team balance", | |
author = "kimoto", | |
description = "auto team balance plugin", | |
version = PLUGIN_VERSION, | |
url = "" | |
} | |
public OnPluginStart() | |
{ | |
RegConsoleCmd("autobalance", Command_AutoBalance) | |
RegConsoleCmd("debug_autobalance", Command_DebugAutoBalance) | |
} | |
public OnMapStart() | |
{ | |
AutoBalance(0); | |
} | |
public AutoBalance(client) | |
{ | |
PrintToConsole(client, "******* do autobalance!!"); | |
new Handle:players = INVALID_HANDLE; // dynamic array | |
new Handle:survivors = INVALID_HANDLE; | |
new Handle:infected = INVALID_HANDLE; | |
new Handle:spectators = INVALID_HANDLE; | |
players = CreateArray(ARRAY_SIZE); | |
survivors = CreateArray(ARRAY_SIZE); | |
infected = CreateArray(ARRAY_SIZE); | |
spectators = CreateArray(ARRAY_SIZE); | |
// calc all players | |
for(new i=1; i<=GetMaxClients(); i++) | |
{ | |
// ingame and not bot player | |
if(IsClientInGame(i) && !IsClientBot(i)) | |
{ | |
PushArrayCell(players, i); | |
if(GetClientTeam(i) == TEAM_INFECTED) | |
{ | |
// infected player | |
PushArrayCell(infected, i); | |
}else if(GetClientTeam(i) == TEAM_SURVIVOR) | |
{ | |
// survivor player | |
PushArrayCell(survivors, i); | |
}else if(GetClientTeam(i) == TEAM_SPECTATE) | |
{ | |
// spectate player | |
PushArrayCell(spectators, i); | |
}else{ | |
DebugPrint("-------- not implemented code: %d", GetClientTeam(i)); | |
} | |
} | |
} | |
DebugPrint("players: %d", GetArraySize(players)); | |
DebugPrint("survivors: %d", GetArraySize(survivors)); | |
DebugPrint("infected: %d", GetArraySize(infected)); | |
DebugPrint("spectators: %d", GetArraySize(spectators)); | |
// validate min players | |
//if(GetArraySize(players) <= MIN_PLAYER_SIZE) | |
// return false; | |
// execute autobalance core | |
AutoBalanceCore(client, players, survivors, infected, spectators); | |
return true; // success; | |
} | |
public AutoBalanceCore(client, players, survivors, infected, spectators) | |
{ | |
// min check | |
if( GetArraySize(players) <= MIN_PLAYER_SIZE ) | |
{ | |
DebugPrint("not auto-balanced: players(%d) <= MIN_PLAYER_SIZE(%d)", GetArraySize(players), MIN_PLAYER_SIZE); | |
return false; | |
} | |
new Handle:active_players = CreateArray(ARRAY_SIZE); | |
new Handle:purpose_survivors = CreateArray(ARRAY_SIZE); | |
new Handle:purpose_infected = CreateArray(ARRAY_SIZE); | |
// make active players list | |
for(new i=0; i<GetArraySize(survivors); i++) | |
{ | |
PushArrayCell(active_players, GetArrayCell(survivors, i)); | |
} | |
for(new i=0; i<GetArraySize(infected); i++) | |
{ | |
PushArrayCell(active_players, GetArrayCell(infected, i)); | |
} | |
DebugPrint("shuffle array"); | |
inspect( ShuffleArray(active_players) ); | |
DebugPrint("######### active players"); | |
inspect(active_players); | |
new total_size = GetArraySize(active_players) | |
new half_size = total_size / 2; | |
for(new i=0; i<total_size; i++) | |
{ | |
if(0 <= i && i< half_size) | |
{ | |
PushArrayCell(purpose_survivors, GetArrayCell(active_players, i)); | |
} | |
else | |
{ | |
PushArrayCell(purpose_infected, GetArrayCell(active_players, i)); | |
} | |
} | |
DebugPrint("************* purpose"); | |
inspect(purpose_survivors); | |
inspect(purpose_infected); | |
// stay survivor players | |
new Handle:need_players = ArraySubtraction(purpose_survivors, survivors); | |
// go away survivor players | |
new Handle:not_need_players = ArraySubtraction(survivors, purpose_survivors); | |
DebugPrint("*************** array sub"); | |
inspect( need_players ); | |
inspect( not_need_players ); | |
new n = 0; | |
// auto balance core loop | |
while(true) | |
{ | |
// end condition | |
if(GetArraySize(need_players) == 0 && GetArraySize(not_need_players) == 0) | |
{ | |
break; | |
} | |
if(n > ESCAPE_LOOP_COUNT){ | |
DebugPrint("******** emergency escape routine"); | |
break; | |
} | |
// pickup not need player one | |
new not_need_player = ArrayShift(not_need_players); | |
if(not_need_player != -1) | |
{ | |
DebugPrint("# not need player going spectator"); | |
FindRemoveValueInArray(survivors, not_need_player); | |
// TODO: change team to spectator | |
ChangeClientTeamWrapper(not_need_player, TEAM_SPECTATE); | |
PushArrayCell(spectators, not_need_player); | |
//inspect(survivors); | |
} | |
// pickup need player one, please come here survivor from infected | |
new need_player = ArrayShift(need_players); | |
if(need_player != -1) | |
{ | |
DebugPrint("# need player going survivor"); | |
PushArrayCell(survivors, need_player); | |
FindRemoveValueInArray(infected, need_player); | |
// TODO: change team to survivor | |
ChangeClientTeamWrapper(need_player, TEAM_SURVIVOR); | |
} | |
// not need player(tmp spectator -> to -> infected) | |
if(not_need_player != -1) | |
{ | |
DebugPrint("# go tmp spectator to infected"); | |
PushArrayCell(infected, not_need_player); | |
FindRemoveValueInArray(spectators, not_need_player); | |
// TODO: change team to infected | |
ChangeClientTeamWrapper(not_need_player, TEAM_INFECTED); | |
} | |
n++; | |
} | |
// result debug print | |
DebugPrint("***survivors"); | |
inspect(survivors); | |
DebugPrint("***infected"); | |
inspect(infected); | |
DebugPrint("***spectators"); | |
inspect(spectators); | |
} | |
public Action:Command_AutoBalance(client, args) | |
{ | |
AutoBalance(client); | |
} | |
#define INSPECT_BUFFER_SIZE 512 | |
#define INSPECT_VALUE_BUFFER_SIZE 256 | |
public inspect(array) | |
{ | |
decl String:buffer[INSPECT_BUFFER_SIZE] = ""; | |
for(new i=0; i<GetArraySize(array); i++) | |
{ | |
decl String:value[INSPECT_VALUE_BUFFER_SIZE] = ""; | |
IntToString(GetArrayCell(array, i), value, sizeof(value)); | |
StrCat(buffer, INSPECT_BUFFER_SIZE, value); | |
StrCat(buffer, INSPECT_BUFFER_SIZE, ","); | |
} | |
DebugPrint(buffer); | |
} | |
public ShuffleArray(array) | |
{ | |
new N = GetArraySize(array); | |
for(new i=1; i<N; i++) | |
{ | |
//new a = GetRandomInt(0, i + 1); | |
new a = GetRandomInt(0, i); | |
// swap | |
new iValue = GetArrayCell(array, i); | |
new aValue = GetArrayCell(array, a); | |
SetArrayCell(array, i, aValue); | |
SetArrayCell(array, a, iValue); | |
} | |
return array; | |
} | |
// array subtraction | |
// return is a - b | |
public ArraySubtraction(a, b) | |
{ | |
new Handle:subArray = CreateArray(ARRAY_SIZE); | |
for(new i=0; i<GetArraySize(a); i++) | |
{ | |
new bool:bExist = false; | |
// ikko mo itti sinakattara subtraction array ni ireru | |
for(new j=0; j<GetArraySize(b); j++) | |
{ | |
if(GetArrayCell(a, i) == GetArrayCell(b, j)) bExist = true; | |
} | |
// ikko demo itti sita toiu koto! | |
if(bExist == false) | |
{ | |
PushArrayCell(subArray, GetArrayCell(a, i)); | |
} | |
} | |
return subArray; | |
} | |
public ArrayShift(a) | |
{ | |
if(GetArraySize(a) == 0) | |
return -1; | |
new value = GetArrayCell(a, 0); | |
RemoveFromArray(a, 0); | |
return value; | |
} | |
public FindRemoveValueInArray(array, value) | |
{ | |
// find and remove value | |
new target = FindValueInArray(array, value); | |
new removed_value = GetArrayCell(array, target); | |
RemoveFromArray(array, target); | |
return removed_value; | |
} | |
public ChangeClientTeamWrapper(client, team) | |
{ | |
DebugPrint("change client team ->: %d", team); | |
if(IsClientInGame(client)) | |
ChangeClientTeam(client, team); | |
} | |
public Action:Command_DebugAutoBalance(client, args) | |
{ | |
// nise no steam id jyouhou tokawo kisai sita test data | |
new Handle:players = INVALID_HANDLE; // dynamic array | |
new Handle:survivors = INVALID_HANDLE; | |
new Handle:infected = INVALID_HANDLE; | |
new Handle:spectators = INVALID_HANDLE; | |
players = CreateArray(ARRAY_SIZE); | |
survivors = CreateArray(ARRAY_SIZE); | |
infected = CreateArray(ARRAY_SIZE); | |
spectators = CreateArray(ARRAY_SIZE); | |
PushArrayCell(players, 1); | |
PushArrayCell(players, 2); | |
PushArrayCell(players, 3); | |
PushArrayCell(players, 4); | |
PushArrayCell(players, 5); | |
PushArrayCell(players, 6); | |
PushArrayCell(players, 7); | |
PushArrayCell(players, 8); | |
PushArrayCell(players, 9); | |
PushArrayCell(players, 10); | |
PushArrayCell(players, 11); | |
PushArrayCell(players, 12); | |
PushArrayCell(survivors, 1); | |
PushArrayCell(survivors, 2); | |
PushArrayCell(survivors, 3); | |
PushArrayCell(survivors, 4); | |
PushArrayCell(infected, 5); | |
PushArrayCell(infected, 6); | |
PushArrayCell(infected, 7); | |
PushArrayCell(infected, 8); | |
PushArrayCell(spectators, 9); | |
PushArrayCell(spectators, 10); | |
PushArrayCell(spectators, 11); | |
PushArrayCell(spectators, 12); | |
/* | |
DebugPrint("====== array test"); | |
DebugPrint("return: %d", ArrayShift(survivors)); | |
DebugPrint("return: %d", ArrayShift(survivors)); | |
DebugPrint("return: %d", ArrayShift(survivors)); | |
DebugPrint("return: %d", ArrayShift(survivors)); | |
DebugPrint("return: %d", ArrayShift(survivors)); | |
*/ | |
inspect(survivors); | |
// execute autobalance core | |
AutoBalanceCore(client, players, survivors, infected, spectators); | |
} | |
#define MAX_LINE_WIDTH 64 | |
public IsClientBot(client) | |
{ | |
decl String:SteamID[MAX_LINE_WIDTH]; | |
GetClientAuthString(client, SteamID, sizeof(SteamID)); | |
if (StrEqual(SteamID, "BOT")) | |
return true; | |
return false; | |
} | |
#define DEBUG_PRINT_BUFFER_SIZE 128 | |
public DebugPrint(const String:Message[], any:...) | |
{ | |
if (g_bDebug) | |
{ | |
decl String:DebugBuff[DEBUG_PRINT_BUFFER_SIZE]; | |
VFormat(DebugBuff, sizeof(DebugBuff), Message, 2); | |
LogMessage(DebugBuff); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment