AdminMod.de https://www.adminmod.de/ |
|
plugin pbt ? https://www.adminmod.de/viewtopic.php?t=2727 |
Seite 1 von 1 |
Autor: | [BC]Daniel [ 27.04.2002, 20:20 ] |
Betreff des Beitrags: | plugin pbt ? |
kann mir wer sagen was das ding hier macht ???? und welchen befehl man dann eingeben muss wenn das plug in greift ? hier die sma /* Ptahhotep's Team Balancer (PTB) Version 1.4 File: plugin_cs_ptb.sma Author: Ptahhotep (ptahhotep@planethalflife.com) Testers: all the great guys at http://www.concarne.org Date: 02/19/2002 Introduction ------------ PTB is an Adminmod plugin (http://www.adminmod.org). LogD (http://logd.sourcforge.net) is required to run PTB. PTB is a Counter-Strike (CS) specific plugin. To run PTB with its default settings, simply compile it for your operating system, include it into plugin.ini and change the map on your CS server. PTB detects situations, in which one team rules over the other. It looks at the current team scores, current team win streaks and the current team ratings and decides on actions with the help of these values. Features -------- - team strength evaluation based on scores, streaks, kills, deaths and size - announcement of team balance status once per round - announcement of each WTJ (winning team joining/joiner) try - prevention of WTJ - display of WTJ count (per map) - force into losing or smaller team for WTJ count 4 - log WTJ in wtj.log for WTJ count >= 4 (once per map) - kick for WTJ count >= 10 - automatic dead only team switches - top winner against bottom loser - automatic dead only team transfers - top winner to loser team - overriden auto-join function, that is always choosing the right team and prevents joining of the same or winning or bigger team - display of PTB evaluation status - lots of configuration options Latest Changes -------------- Version 1.4 + FIXED: PTB didn't work the first time a player chooses a team + NEW: PTB sets team strength to team size, if team has no single kill yet (fix for team inbalance in the first rounds of a map) + NEW: switching/transfering alive, if dead only is not possible repeatedly Version 1.3 + NEW: announcing team switch/transfer failures as typesay message + NEW: added "sayok" option + FIXED: completely reworked the options interface, which didn't work at all + WORKAROUND: retrying calculation for negative results on division of 2 positive numbers + REMOVED: command admin_ptb_stats no longer exists Version 1.2a + FIXED: compile error with Adminmod 2.50.26 (plugin_connect syntax change in Adminmod?) Version 1.2 + NEW: display WTJ count + NEW: kick for WTJ count 10 or greater + NEW: force players into losing/smaller team for WTJ count > 3 + NEW: save player name and WONID in wtj.log for WTJ count > 3 + NEW: changed rating to incorporate team sizes + NEW: added switch dead only mode + NEW: added lots of configuration variables + NEW: added team advantage announcements + FIXED: trying to switch player that had already changed teams in the same round Details ------- The current team strength ist defined as sum of team kills divided by sum if team deaths times players in the team (strength = kills/deaths * players). Example: CT kills/deaths: 12/6 = 2 CT players: 3 CT strength: 2 * 3 = 6 T kills/deaths: 4/10 = 0.4 T players: 4 T strength: 0.4 * 4 = 1.6 The current team strength rating is calculated by dividing the team's strength by the opposing team's strength (rating = ownStrength / opposingStrength). Example (continued): CT strength rating: 2/1.6 = 1.25 T strength rating: 1.6/2 = 0.8 For each team these criteria are checked: - rating >= minRating (stronger team) and score > maxScoreDiff - rating >= minRating (stronger team) and streak > maxStreak - rating >= maxRating (stronger team) and more players - rating >= maxRating (way stronger team) If any TWO of these criteria match for a team, it is considered to be the winning team and actions are taken as appropriate. Note: Teams with a rating below minRating are considered as of equal or very similar strength. If team strengths are very similar, streaks and scores are ignored. As soon as a team gets noticibly stronger than it's opposing team, scores, streaks and team size are checked. Configuration ------------- PTB Required Variable Settings: allow_client_exec 1 - needed to switch players' teams admin_balance_teams 0 - switch other team balancing methods off mp_autoteambalance 0 - switch off inbuild CS team balancing mp_limitteams 10 - enable any team size difference PTB Commands: admin_ptb - show PTB statistics (ACCESS_ALL) admin_ptb on - enable all PTB functions admin_ptb off - disable all PTB functions admin_ptb status - show PTB status admin_ptb kick on|off (default: on) - PTB kicking admin_ptb switch on|off (default: on) - PTB team switching and transfers admin_ptb announce on|off (default: on) - PTB announcements admin_ptb sayok on|off (default: on) - PTB "no action required" message admin_ptb limitjoin on|off (default: on) - PTB team join limitations admin_ptb savewtj on|off (default: off) - PTB wtj.log writing admin_ptb deadonly on|off (default: on) - switch dead only or alive, too admin_ptb maxstreak <value> (default: 2) - maximum accepted team win streak admin_ptb maxscore <value> (default: 2) - maximum accepted team score difference admin_ptb maxrandom <value> (default: 3) - range of top/bottom players to choose from for switch/transfer admin_ptb maxrating <value> (default: 2) - way stronger team, if rating >= maxrating admin_ptb minrating <value> (default: 1.5) - stronger team, if rating >= minrating (don't play with these, if you don't fully understand, what it means) // SERVER VARIABLES ARE NOT WORKING ... PTB Server Variables (only used as defaults when set in server.cfg or listenserver.cfg) -------------------- admin_ptb_kick on|off (default: on) - PTB kicking admin_ptb_switch on|off (default: on) - PTB team switching and transfers admin_ptb_announce on|off (default: on) - PTB announcements admin_ptb_sayok on|off (default: on) - PTB "no action required" message admin_ptb_limitjoin on|off (default: on) - PTB team join limitations admin_ptb_savewtj on|off (default: off) - PTB wtj.log writing admin_ptb_deadonly on|off (default: on) - switch dead only or alive, too admin_ptb_maxstreak <value> (default: 2) - maximum accepted team win streak admin_ptb_maxscore <value> (default: 2) - maximum accepted team score difference admin_ptb_maxrandom <value> (default: 3) - range of top/bottom players to choose from for switch/transfer admin_ptb_maxrating <value> (default: 2) - way stronger team, if rating >= maxrating admin_ptb_minrating <value> (default: 1.5) - stronger team, if rating >= minrating (don't play with these, if you don't fully understand, what it means) // SERVER VARIABLES ARE NOT WORKING ... SUGGESTIONS & TODO ------------------ Ender - invent map type factors (de_, cs_, as_) KNOWN BUGS ---------- - sometimes dividing 2 positive fixed numbers yields a negative number */ #pragma dynamic 32768 #include <core> #include <console> #include <string> #include <admin> #include <adminlib> #include <fixed> new STRING_VERSION[MAX_DATA_LENGTH] = "1.4"; #define ACCESS_BALANCE 32 #define ACCESS_CONSOLE 131072 #define TS 1 #define CTS 2 #define AUTO_TEAM 5 #define MAX_TEAM_SIZE 10 #define MAX_SCORE_DIFF 2 #define MAX_STREAK 2 #define MAX_RANDOM 3 new MIN_RATING[10] = "1.5"; new MAX_RATING[10] = "2"; // options new option_kick = 1; new option_switch = 1; new option_announce = 1; new option_sayok = 1; new option_limitjoin = 1; new option_savewtj = 0; new option_deadonly = 1; new option_maxstreak = 2; new option_maxscore = 2; new option_maxrandom = 3; new fixed:option_maxrating; new fixed:option_minrating; new sortedTeams[3][MAX_PLAYERS + 1]; new nonDeadTeamCounts[3]; new sortedNonDeadTeams[3][MAX_PLAYERS + 1]; new kills[MAX_PLAYERS + 1] = { 0, ... }; new deaths[MAX_PLAYERS + 1] = { 0, ... }; new teamKills[3] = { 0, ... }; new teamDeaths[3] = { 0, ... }; new teamScores[3] = { 0, ... }; new winStreaks[3] = { 0, ... }; new wtConditions[3]; new winnerTeam = 0; new loserTeam = 0; new fixed:ctKD; new fixed:tKD; new fixed:ctStrength; new fixed:tStrength; new fixed:ctRating; new fixed:tRating; new isChoosingTeam[MAX_PLAYERS + 1]; new isBeingTransfered[MAX_PLAYERS + 1]; new playerTeam[MAX_PLAYERS + 1]; new switchedThisRound[MAX_PLAYERS + 1]; new wtjCount[MAX_PLAYERS + 1]; new teamCounts[3] = { 0, ... }; #define SWITCH_ALIVE_OVERRIDE 2 new couldNotSwitchCounter = 0; /* public admin_transfer(HLCommand, HLData, HLUserName, UserIndex) { new Data[MAX_DATA_LENGTH]; convert_string(HLData, Data, MAX_DATA_LENGTH); new i = strtonum(Data); if (i >= 1 && i <= MAX_PLAYERS) transferPlayer(i); } public admin_spectator(HLCommand, HLData, HLUserName, UserIndex) { new Data[MAX_DATA_LENGTH]; convert_string(HLData, Data, MAX_DATA_LENGTH); new i = strtonum(Data); if (i >= 1 && i <= MAX_PLAYERS) { new Name[MAX_NAME_LENGTH]; playerinfo(i, Name, MAX_NAME_LENGTH); execclient(Name, "chooseteam; menuselect 6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); } } */ transferPlayer(player) { //say("transferPlayer"); new Name[MAX_NAME_LENGTH]; playerinfo(player, Name, MAX_NAME_LENGTH); if (playerTeam[player] == CTS || playerTeam[player] == TS) { isBeingTransfered[player] = 1; //say("Transferring Player:"); //say(Name); if (playerTeam[player] == TS) { execclient(Name, "chooseteam; menuselect 2; menuselect 5"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); } else { execclient(Name, "chooseteam; menuselect 1; menuselect 5"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); execclient(Name, "wait; wait; wait; slot6, wait; wait; wait; slot6"); } } else { //say("Player Not In A Team:"); //say(Name); } } act() { //say("act"); if (!option_switch) return; say("PTB: Round ended, checking teams."); checkTeamBalance(); if (winnerTeam != 0) { sortTeam(CTS); sortTeam(TS); if (teamCounts[winnerTeam] <= teamCounts[loserTeam]) doSwitch(); else if (teamCounts[loserTeam] < teamCounts[winnerTeam]) doTransfer(); //new text[MAX_TEXT_LENGTH]; //snprintf(text, MAX_TEXT_LENGTH, "Winners: %d, Losers: %d", winners, losers); //say(text); } } createNonDeadTeam(theTeam) { new Name[MAX_NAME_LENGTH]; new WonId; new UserId; new team; new dead; //say("createNonDeadTeam"); new n = 0; for (new i = 0; i < teamCounts[theTeam]; ++i) { if (0 == playerinfo(sortedTeams[theTeam], Name, MAX_NAME_LENGTH, WonId, UserId, team, dead)) { //say("No playerinfo ..."); } //snprintf(Name, MAX_NAME_LENGTH, "Index: %d, sortedTeamIndex: %d, dead: %d", i , sortedTeams[theTeam], dead); //say(Name); if (dead == 0) { //say("player alive"); continue; } //say("player dead"); sortedNonDeadTeams[theTeam][n] = sortedTeams[theTeam]; ++n; } nonDeadTeamCounts[theTeam] = n; } sortTeam(theTeam) { //say("sortTeam"); // create list of players new n = 0; for (new i = 1; i <= MAX_PLAYERS; ++i) { if (playerTeam != theTeam) continue; sortedTeams[theTeam][n] = i; ++n; } // do a selection sort new count = teamCounts[theTeam]; for (new i = count - 1; i > 0; --i) { for (new k = i - 1; k >= 0; --k) { // compare players if ( (kills[sortedTeams[theTeam][k]] < kills[sortedTeams[theTeam]]) || ( (kills[sortedTeams[theTeam][k]] == kills[sortedTeams[theTeam]]) && (deaths[sortedTeams[theTeam][k]] > deaths[sortedTeams[theTeam]]) ) ) { // swap new t; t = sortedTeams[theTeam][k]; sortedTeams[theTeam][k] = sortedTeams[theTeam]; sortedTeams[theTeam] = t; } } } } doSwitch() { //say("doSwitch"); new text[MAX_TEXT_LENGTH]; //displayStatistics(true); // don't switch, if at least one team is empty if (teamCounts[winnerTeam] == 0 || teamCounts[loserTeam] == 0) { text = "PTB: Can't switch players, need players in each team." typesay(text, 5, 10, 255, 10); say(text); return; } // don't switch, if winner is alone (RULER!!!) if (teamCounts[winnerTeam] == 1) { text = "PTB: Won't switch players, only one player in winning team." typesay(text, 5, 10, 255, 10); say(text); return; } // don't switch, if both teams are full if (teamCounts[winnerTeam] == MAX_TEAM_SIZE && teamCounts[loserTeam] == MAX_TEAM_SIZE) { text = "PTB: Can't switch players, both teams are full." typesay(text, 5, 10, 255, 10); say(text); return; } new winner; new loser; if (!option_deadonly || couldNotSwitchCounter == SWITCH_ALIVE_OVERRIDE) { // choose from random top or bottom x new winnerIndex = random(min(teamCounts[winnerTeam] / 2, option_maxrandom)); new loserIndex = teamCounts[loserTeam] - random(min(teamCounts[loserTeam] / 2, option_maxrandom)); winner = sortedTeams[winnerTeam][winnerIndex]; loser = sortedTeams[loserTeam][loserIndex]; } else { //say("switch dead"); // choose best and worst dead players createNonDeadTeam(winnerTeam); createNonDeadTeam(loserTeam); if (nonDeadTeamCounts[winnerTeam] == 0 || nonDeadTeamCounts[loserTeam] == 0) { strcpy(text, "PTB: Can't switch players, need dead player in each team.", MAX_DATA_LENGTH); ++couldNotSwitchCounter; if (couldNotSwitchCounter == SWITCH_ALIVE_OVERRIDE) { say("PTB: Couldn't switch dead, switching alive."); doSwitch(); return; } typesay(text, 5, 10, 255, 10); say(text); return; } winner = sortedNonDeadTeams[winnerTeam][0]; loser = sortedNonDeadTeams[loserTeam][nonDeadTeamCounts[loserTeam] - 1]; } couldNotSwitchCounter = 0; if (switchedThisRound[winner] || switchedThisRound[loser]) { strcpy(text, "PTB: Can't switch players, player joined/changed this round already.", MAX_DATA_LENGTH); typesay(text, 5, 10, 255, 10); say(text); return; } new winnerName[MAX_NAME_LENGTH]; new loserName[MAX_NAME_LENGTH]; //new debug[MAX_TEXT_LENGTH]; //snprintf(debug, MAX_TEXT_LENGTH, "Winner Index: %d", winnerIndex); //say(debug); //snprintf(debug, MAX_TEXT_LENGTH, "Loser Index: %d", loserIndex); //say(debug); playerinfo(winner, winnerName, MAX_NAME_LENGTH); playerinfo(loser, loserName, MAX_NAME_LENGTH); // if one team is full, first move the the player from the full team ... if (teamCounts[winnerTeam] == MAX_TEAM_SIZE){ transferPlayer(winner); transferPlayer(loser); } else { transferPlayer(loser); transferPlayer(winner); } strcpy(text, "PTB: Switching ", 80); strcat(text, winnerName, 80); strcat(text, " with ", 80); strcat(text, loserName, 80); strcat(text, ".", 80); typesay(text, 5, 10, 255, 10); say(text); } doTransfer() { //say("doTransfer"); new text[MAX_TEXT_LENGTH]; if (teamCounts[winnerTeam] == 0) return; //displayStatistics(true); if (teamCounts[loserTeam] == MAX_TEAM_SIZE) { strcpy(text, "PTB: Can't transfer player, losing team is full.", MAX_DATA_LENGTH); typesay(text, 5, 10, 255, 10); say(text); return; } new winner; if (!option_deadonly || couldNotSwitchCounter == SWITCH_ALIVE_OVERRIDE) { // choose from random top x new winnerIndex = random(min(teamCounts[winnerTeam] / 2, option_maxrandom)); winner = sortedTeams[winnerTeam][winnerIndex]; } else { // choose best dead player createNonDeadTeam(winnerTeam); if (nonDeadTeamCounts[winnerTeam] == 0) { strcpy(text, "PTB: Can't transfer player, need dead player in winning team.", MAX_DATA_LENGTH); ++couldNotSwitchCounter; if (couldNotSwitchCounter == SWITCH_ALIVE_OVERRIDE) { say("PTB: Couldn't transfer dead, transfering alive."); doTransfer(); return; } typesay(text, 5, 10, 255, 10); say(text); return; } winner = sortedNonDeadTeams[winnerTeam][0]; } couldNotSwitchCounter = 0; if (switchedThisRound[winner]) { strcpy(text, "PTB: Can't transfer player, player joined/changed this round already.", MAX_DATA_LENGTH); typesay(text, 5, 10, 255, 10); say(text); return; } new winnerName[MAX_NAME_LENGTH]; //new debug[MAX_TEXT_LENGTH]; //snprintf(debug, MAX_TEXT_LENGTH, "Winner Index: %d", winnerIndex); //say(debug); playerinfo(winner, winnerName, MAX_NAME_LENGTH); transferPlayer(winner); strcpy(text, "PTB: Transfering ", 80); strcat(text, winnerName, 80); strcat(text, " to the ", 80); if (winnerTeam == CTS) strcat(text, "Ts", 80); else if (winnerTeam == TS) strcat(text, "CTs", 80); strcat(text, ".", 80); typesay(text, 5, 10, 255, 10); say(text); } checkTeamBalance() { //say("Checking team balance ..."); new MAX_TRIES = 10; new tries; calcTeamScores(); ctKD = fixed(teamKills[CTS]); if (teamDeaths[CTS] > 0) { // workaround for negative results on dividing 2 positive numbers tries = 0; while (tries < MAX_TRIES) { ctKD = fdiv(ctKD, fixed(teamDeaths[CTS])); if (ctKD >= fixed(0)) break; ++tries; } } tKD = fixed(teamKills[TS]); if (teamDeaths[TS] > 0) { // workaround for negative results on dividing 2 positive numbers tries = 0; while (tries < MAX_TRIES) { tKD = fdiv(tKD, fixed(teamDeaths[TS])); if (tKD >= fixed(0)) break; ++tries; } } ctStrength = fixed(teamCounts[CTS]); // workaround for match start team balancing // this is making only team size count, // as long as there is no single kill if (ctKD != fixed(0)) ctStrength = fmul(ctKD, ctStrength); tStrength = fixed(teamCounts[TS]); // workaround for match start team balancing // this is making only team size count, // as long as there is no single kill if (tKD != fixed(0)) tStrength = fmul(tKD, tStrength); ctRating = ctStrength; if (tStrength > fixed(0)) { // workaround for negative results on dividing 2 positive numbers tries = 0; while (tries < MAX_TRIES) { ctRating = fdiv(ctRating, tStrength); if (ctRating >= fixed(0)) break; ++tries; } } tRating = tStrength; if (ctStrength > fixed(0)) { // workaround for negative results on dividing 2 positive numbers tries = 0; while (tries < MAX_TRIES) { tRating = fdiv(tRating, ctStrength); if (tRating >= fixed(0)) break; ++tries; } } wtConditions[TS] = 0; wtConditions[CTS] = 0; //new buffer[10]; // compare scores for unequal rating scores if (teamScores[TS] - teamScores[CTS] > option_maxscore && tRating >= option_minrating) { wtConditions[TS] = wtConditions[TS] + 1; } if (teamScores[CTS] - teamScores[TS] > option_maxscore && ctRating >= option_minrating) { wtConditions[CTS] = wtConditions[CTS] + 1; } //say("// check streaks for unequal rating scores"); // check streaks for unequal rating scores if (winStreaks[TS] > option_maxstreak && tRating >= option_minrating) { wtConditions[TS] = wtConditions[TS] + 1; } if (winStreaks[CTS] > option_maxstreak && ctRating >= option_minrating) { wtConditions[CTS] = wtConditions[CTS] + 1; } //say("// check ratings"); // check ratings if (tRating >= option_maxrating) { wtConditions[TS] = wtConditions[TS] + 1; } if (ctRating >= option_maxrating) { wtConditions[CTS] = wtConditions[CTS] + 1; } //say("// check team sizes for unequal ratings"); // check team sizes for unequal ratings if (teamCounts[TS] > teamCounts[CTS] && tRating >= option_minrating) { wtConditions[TS] = wtConditions[TS] + 1; } if (teamCounts[CTS] > teamCounts[TS] && ctRating >= option_minrating) { wtConditions[CTS] = wtConditions[CTS] + 1; } //say("// check conditions"); // check conditions if (wtConditions[TS] >= 2) { //say("TERRORISTS are the winning team ..."); winnerTeam = TS; loserTeam = CTS; } else if (wtConditions[CTS] >= 2) { //say("COUNTER-TERRORISTS are the winning team ..."); winnerTeam = CTS; loserTeam = TS; } else { winnerTeam = 0; loserTeam = 0; //if (wtConditions[CTS] > 0) say("COUNTER-TERRORIST team advantage ..."); //else if (wtConditions[TS] > 0) say("TERRORIST team advantage ..."); //else say("No winning team, no team advantage ..."); } } public ChoosingTeam(HLCommand, HLData, HLUserName, UserIndex) { //say("ChoosingTeam"); isChoosingTeam[UserIndex] = 1; return PLUGIN_CONTINUE; } public NotChoosingTeam(HLCommand, HLData, HLUserName, UserIndex) { //say("NotChoosingTeam"); isChoosingTeam[UserIndex] = 0; return PLUGIN_CONTINUE; } manageWtjFile(UserIndex) { if (!option_savewtj) return; //log("Trying to write wtj.log ...."); if (wtjCount[UserIndex] != 4) return; //log("wtj.log should be written to now ...."); //new debug[MAX_DATA_LENGTH]; //snprintf(debug, MAX_DATA_LENGTH, "PTB manageWtjFile"); //log(debug); new Time[MAX_DATA_LENGTH]; servertime(Time, MAX_DATA_LENGTH); new Map[MAX_DATA_LENGTH]; currentmap(Map, MAX_DATA_LENGTH); new Name[MAX_NAME_LENGTH]; new UserId; new WonId; playerinfo(UserIndex, Name, MAX_NAME_LENGTH, UserId, WonId); new text[MAX_TEXT_LENGTH]; snprintf(text, MAX_TEXT_LENGTH, "%s %s <%d> %s", Time, Name, WonId, Map); writefile("wtj.log", text); } public MenuSelect(HLCommand, HLData, HLUserName, UserIndex) { //say("MenuSelect"); /* new s[MAX_TEXT_LENGTH]; new d[MAX_DATA_LENGTH]; new n[MAX_NAME_LENGTH]; convert_string(HLData, d, MAX_DATA_LENGTH); convert_string(HLUserName, n, MAX_DATA_LENGTH); snprintf(s, MAX_TEXT_LENGTH, "%s (%d) selected menu %s (is choosing team: %d)", n, UserIndex, d, isChoosingTeam[UserIndex]); say(s); */ if (!isChoosingTeam[UserIndex]) return PLUGIN_CONTINUE; isChoosingTeam[UserIndex] = 0; //if (UserIndex < 1) return PLUGIN_CONTINUE; if (!option_limitjoin) return PLUGIN_CONTINUE; if (isBeingTransfered[UserIndex]) { //say("TRANSFER"); isBeingTransfered[UserIndex] = 0; return PLUGIN_CONTINUE; } else { //say("NO TRANSFER"); } new Data[MAX_DATA_LENGTH]; new iNewTeam; convert_string(HLData, Data, MAX_DATA_LENGTH); iNewTeam = strtonum(Data); new iOldTeam = playerTeam[UserIndex]; new Name[MAX_NAME_LENGTH]; playerinfo(UserIndex, Name, MAX_NAME_LENGTH); // prevent unwanted rejoining of the same team ... if (iNewTeam == playerTeam[UserIndex]) { //say("Preventing rejoining of the same team."); return PLUGIN_HANDLED; } checkTeamBalance(); //displayStatistics(true); // debug //snprintf(s, MAX_TEXT_LENGTH, "iOldTeam = %d, iNewTeam = %d, winnerTeam = %d, loserTeam = %d, CTS = %d, TS = %d, AUTO_TEAM = %d, #CTs = %d, #Ts = %d", iOldTeam, iNewTeam, winnerTeam, loserTeam, CTS, TS, AUTO_TEAM, teamCounts[CTS], teamCounts[TS]); //say(s); // check if player is trying to change teams if ((iNewTeam == CTS || iNewTeam == TS) && (iOldTeam == CTS || iOldTeam == TS)) { //say("Changing team directly."); new opposingTeam = iNewTeam == CTS ? TS : CTS; if ( teamCounts[iNewTeam] != 0 && teamCounts[opposingTeam] < MAX_TEAM_SIZE && ( (winnerTeam != 0 && iNewTeam == winnerTeam) || (teamCounts[iNewTeam] >= teamCounts[opposingTeam]) ) ) { new text[MAX_TEXT_LENGTH]; wtjCount[UserIndex] += 1; if (wtjCount[UserIndex] > 9 && option_kick) { snprintf(text, 80, "PTB: Kicking %s for a WTJ count of %d).", Name, wtjCount[UserIndex]); typesay(text, 5, 10, 255, 10); say(text); kick(Name); return PLUGIN_HANDLED; } if (iNewTeam == CTS) { snprintf(text, 80, "PTB: The CTs are strong enough, %s (WTJ count: %d).", Name, wtjCount[UserIndex]); typesay(text, 5, 10, 10, 255); } else { snprintf(text, 80, "PTB: The Ts are strong enough, %s (WTJ count: %d).", Name, wtjCount[UserIndex]); typesay(text, 5, 255, 10, 10); } say(text); return PLUGIN_HANDLED; } } else if (iNewTeam == CTS || iNewTeam == TS) { //say("Joining team directly."); new opposingTeam = iNewTeam == CTS ? TS : CTS; if ( teamCounts[iNewTeam] != 0 && teamCounts[opposingTeam] < MAX_TEAM_SIZE && ( (winnerTeam != 0 && iNewTeam == winnerTeam) // && teamCounts[winnerTeam] >= teamCounts[opposingTeam]) || (winnerTeam == 0 && teamCounts[iNewTeam] > teamCounts[opposingTeam]) ) ) { new text[MAX_TEXT_LENGTH]; wtjCount[UserIndex] += 1; if (wtjCount[UserIndex] > 9 && option_kick) { snprintf(text, 80, "PTB: Kicking %s for a WTJ count of %d).", Name, wtjCount[UserIndex]); typesay(text, 5, 10, 255, 10); say(text); kick(Name); return PLUGIN_HANDLED; } if (iNewTeam == CTS) { if (wtjCount[UserIndex] > 3) { manageWtjFile(UserIndex); snprintf(text, 80, "PTB: Forcing %s to the Ts (WTJ count: %d).", Name, wtjCount[UserIndex]); execclient(Name, "menuselect 1"); typesay(text, 5, 10, 255, 10); } else { snprintf(text, 80, "PTB: The CTs are strong enough, %s (WTJ count: %d).", Name, wtjCount[UserIndex]); typesay(text, 5, 10, 10, 255); } } else { if (wtjCount[UserIndex] > 3) { manageWtjFile(UserIndex); snprintf(text, 80, "PTB: Forcing %s to the CTs (WTJ count: %d).", Name, wtjCount[UserIndex]); execclient(Name, "menuselect 2"); typesay(text, 5, 10, 255, 10); } else { snprintf(text, 80, "PTB: The Ts are strong enough, %s (WTJ count: %d).", Name, wtjCount[UserIndex]); typesay(text, 5, 255, 10, 10); } } say(text); return PLUGIN_HANDLED; } } else if (iNewTeam == AUTO_TEAM && (iOldTeam == CTS || iOldTeam == TS)) { //say("Changing team automatically."); new opposingTeam = iOldTeam == CTS ? TS : CTS; if ( teamCounts[opposingTeam] != 0 && ( opposingTeam == MAX_TEAM_SIZE || (loserTeam != 0 && iOldTeam == loserTeam) || (loserTeam == 0 && teamCounts[iOldTeam] <= teamCounts[opposingTeam]) ) ) { //say("Aborting automatic team change."); // debug //new text[MAX_TEXT_LENGTH]; //snprintf(text, MAX_TEXT_LENGTH, "Aborting auto-joining team %d (winnerTeam = %d) teamCounts[iOldTeam] %d teamCounts[opposingTeam] %d", opposingTeam, winnerTeam, teamCounts[iOldTeam], teamCounts[opposingTeam]); //say(text); // close menu return PLUGIN_HANDLED; } iNewTeam = opposingTeam; // debug //new text[MAX_TEXT_LENGTH]; //snprintf(text, MAX_TEXT_LENGTH, "Auto-joining team %d. (winnerTeam = %d)", iNewTeam, winnerTeam); //say(text); if (iNewTeam == CTS) execclient(Name, "menuselect 2"); else execclient(Name, "menuselect 1"); return PLUGIN_HANDLED; } else if (iNewTeam == AUTO_TEAM) { //say("Joining team automatically."); /* this is the "always smaller team" version if (teamCounts[CTS] < teamCounts[TS] || teamCounts[TS] == MAX_TEAM_SIZE) iNewTeam = CTS; else if (teamCounts[TS] < teamCounts[CTS] || teamCounts[CTS] == MAX_TEAM_SIZE) iNewTeam = TS; // both teams have same size ... else if (winnerTeam != 0 && teamCounts[loserTeam] < MAX_TEAM_SIZE) iNewTeam = loserTeam; else if (teamCounts[TS] == MAX_TEAM_SIZE) iNewTeam = CTS; else if (teamCounts[CTS] == MAX_TEAM_SIZE) iNewTeam = TS; else iNewTeam = random(2) + 1; */ // this version prefers the losing team if (winnerTeam != 0 && teamCounts[loserTeam] < MAX_TEAM_SIZE) iNewTeam = loserTeam; else if (teamCounts[CTS] < teamCounts[TS] || teamCounts[TS] == MAX_TEAM_SIZE) iNewTeam = CTS; else if (teamCounts[TS] < teamCounts[CTS] || teamCounts[CTS] == MAX_TEAM_SIZE) iNewTeam = TS; // both teams have same size ... else if (teamCounts[TS] == MAX_TEAM_SIZE) iNewTeam = CTS; else if (teamCounts[CTS] == MAX_TEAM_SIZE) iNewTeam = TS; else iNewTeam = random(2) + 1; // debug //new text[MAX_TEXT_LENGTH]; //snprintf(text, MAX_TEXT_LENGTH, "Auto-joining team %d. (winnerTeam = %d)", iNewTeam, winnerTeam); //say(text); if (iNewTeam == CTS) execclient(Name, "menuselect 2"); else execclient(Name, "menuselect 1"); return PLUGIN_HANDLED; } //say("Allow team join ..."); return PLUGIN_CONTINUE; } public ptb_teamaction(HLCommand, HLData, HLUserName, UserIndex) { //say("ptb_teamaction"); new params[MAX_DATA_LENGTH]; new team[MAX_DATA_LENGTH]; new action[MAX_DATA_LENGTH]; convert_string(HLData, params, MAX_DATA_LENGTH); strbreak(params, team, action, MAX_DATA_LENGTH); if( strmatch(action, "CTs_Win", strlen("CTs_Win")) || strmatch(action, "Terrorists_Win", strlen("Terrorists_Win")) || strmatch(action, "Target_Bombed", strlen("Target_Bombed")) ) { new scores[MAX_DATA_LENGTH]; new ctScore[MAX_DATA_LENGTH]; new tScore[MAX_DATA_LENGTH]; new skip[MAX_DATA_LENGTH]; new c; strbreak(action, skip, scores, MAX_DATA_LENGTH); strbreak(scores, ctScore, tScore, MAX_DATA_LENGTH); c = strchr(ctScore, '#') + 1; teamScores[CTS] = strtonum(ctScore[c]); c = strchr(tScore, '#') + 1; teamScores[TS] = strtonum(tScore[c]); // count won rounds in a row if (strmatch(action, "CTs_Win", strlen("CTs_Win"))) { if (winStreaks[CTS] < 0) { // reset counters winStreaks[CTS] = 1; winStreaks[TS] = -1; } else { winStreaks[CTS] += 1; winStreaks[TS] -= 1; } } else { if (winStreaks[TS] < 0) { // reset counters winStreaks[CTS] = -1; winStreaks[TS] = 1; } else { winStreaks[CTS] -= 1; winStreaks[TS] += 1; } } } act(); // clear flags for (new i = 1; i <= MAX_PLAYERS; ++i) switchedThisRound = false; return PLUGIN_CONTINUE; } public ptb_worldaction(HLCommand, HLData, HLUserName, UserIndex) { //say("ptb_worldaction"); new Data[MAX_DATA_LENGTH]; convert_string(HLData, Data, MAX_DATA_LENGTH); //say(Data); if (streq(Data, "Round_Start")) { //set_timer("announceStatus", 15, 1); announceStatus(); } return PLUGIN_CONTINUE; } public ptb_teamselection(HLCommand, HLData, HLUserName, UserIndex) { //say("ptb_teamselection"); //displayStatistics(true); new data[MAX_DATA_LENGTH]; new sIndex[MAX_DATA_LENGTH]; new sTeam[MAX_DATA_LENGTH]; new i; new team; convert_string(HLData, data, MAX_DATA_LENGTH); strsplit(data, " ", sIndex, MAX_DATA_LENGTH, sTeam, MAX_DATA_LENGTH); //new debug[MAX_DATA_LENGTH]; //snprintf(debug, MAX_DATA_LENGTH, "PTB: ptb_teamselection: %s", data); //log(debug); if (streq(sTeam, "TERRORIST")) team = TS; else if (streq(sTeam, "CT")) team = CTS; else team = 0; //if (team == 0) say("PTB: ptb_teamselection: Team is 0."); i = strtonum(sIndex); if (playerTeam[i] == TS || playerTeam[i] == CTS) teamCounts[playerTeam[i]] -= 1; if (team == TS || team == CTS) teamCounts[team] += 1; playerTeam[i] = team; switchedThisRound[i] = true; //say("ptb_teamselection"); //say(data); //displayStatistics(true); return PLUGIN_CONTINUE; } public ptb_kill(HLCommand, HLData, HLUserName, UserIndex) { //say("ptb_kill"); new iWinner; new iLoser; new idWinner[3]; new idLoser[3]; new data[MAX_DATA_LENGTH]; new name[MAX_NAME_LENGTH]; convert_string(HLData, data, MAX_DATA_LENGTH); strsplit(data, " ", idWinner, 3, idLoser, 3); iWinner = strtonum(idWinner); iLoser = strtonum(idLoser); if (!playerinfo(iWinner, name, MAX_NAME_LENGTH)) { return PLUGIN_CONTINUE; } kills[iWinner] = kills[iWinner] + 1; deaths[iLoser] = deaths[iLoser] + 1; if (playerTeam[iWinner] != CTS && playerTeam[iWinner] != TS) log("PTB: Kill without team!"); if (playerTeam[iLoser] != CTS && playerTeam[iLoser] != TS) log("PTB: Death without team!"); return PLUGIN_CONTINUE; } calcTeamScores() { //say("calcTeamScores"); teamDeaths[CTS] = 0; teamDeaths[TS] = 0; teamKills[CTS] = 0; teamKills[TS] = 0; for (new i = 1; i <= MAX_PLAYERS; ++i) { new team = playerTeam[i]; if (team == CTS || team == TS) { teamKills[team] += kills[i]; teamDeaths[team] += deaths[i]; } } /* new text[MAX_TEXT_LENGTH]; snprintf(text, MAX_TEXT_LENGTH, "CT Kill/Deaths: %d/%d", teamKills[CTS], teamDeaths[CTS]); say(text); snprintf(text, MAX_TEXT_LENGTH, "T Kill/Deaths: %d/%d", teamKills[TS], teamDeaths[TS]); say(text); */ //say("calcTeamScores DONE"); } announceStatus() { //say("announceStatus"); if (!option_announce) return; checkTeamBalance(); new text[MAX_TEXT_LENGTH]; if (winnerTeam == TS) { snprintf(text, MAX_TEXT_LENGTH, "PTB: The COUNTER-TERRORIST team could use some support."); typesay(text, 5, 10, 10, 255); say("PTB: The COUNTER-TERRORIST team could use some support."); } else if (winnerTeam == CTS) { snprintf(text, MAX_TEXT_LENGTH, "PTB: The TERRORIST team could use some support."); typesay(text, 5, 255, 10, 10); say("PTB: The TERRORIST team could use some support."); } else if (wtConditions[TS] > wtConditions[CTS]) { snprintf(text, MAX_TEXT_LENGTH, "PTB: Observing TERRORIST team advantage."); typesay(text, 5, 10, 10, 255); say("PTB: Observing TERRORIST team advantage."); } else if (wtConditions[CTS] > wtConditions[TS]) { snprintf(text, MAX_TEXT_LENGTH, "PTB: Observing COUNTER-TERRORIST team advantage."); typesay(text, 5, 255, 10, 10); say("PTB: Observing COUNTER-TERRORIST team advantage."); } else if (option_sayok) { snprintf(text, MAX_TEXT_LENGTH, "PTB: Teams look fine, no action required."); typesay(text, 5, 255, 255, 255); say("PTB: Teams look fine, no action required."); } //displayStatistics(); } public admin_ptb(HLCommand, HLData, HLUserName, UserIndex) { new Data[MAX_DATA_LENGTH]; new Command[MAX_DATA_LENGTH]; new Argument[MAX_DATA_LENGTH]; new s[MAX_TEXT_LENGTH]; convert_string(HLData, Data, MAX_NAME_LENGTH); strinit(Command); strinit(Argument); selfmessage("PTB: Ptahhotep's Team Balancer 1.4"); selfmessage("PTB: (ptahhotep@planethalflife.com)"); if (!strlen(Data)) { displayStatistics(); } else if (!access(ACCESS_BALANCE, "")) { selfmessage("PTB: You are not allowed to use this command"); return PLUGIN_HANDLED; } else if (streq(Data, "on") || streq(Data, "1")) { option_switch = 1; option_announce = 1; option_limitjoin = 1; selfmessage("PTB: Enabled all PTB actions."); return PLUGIN_HANDLED; } else if (streq(Data, "off") || streq(Data, "0")) { option_switch = 0; option_announce = 0; option_limitjoin = 0; selfmessage("PTB: Disabled all PTB actions."); return PLUGIN_HANDLED; } else { strsplit(Data, " ", Command, MAX_DATA_LENGTH, Argument, MAX_DATA_LENGTH); } if (streq(Command, "switch") && strlen(Argument)) option_switch = check_param(Argument); if (streq(Command, "status") || streq(Command, "switch")) { if (option_switch) selfmessage("PTB: (switch) Team switching is ON."); else selfmessage("PTB: (switch) Team switching is OFF."); } if (streq(Command, "announce") && strlen(Argument)) option_announce = check_param(Argument); if (streq(Command, "status") || streq(Command, "announce")) { if (option_announce) selfmessage("PTB: (announce) Announcements are ON."); else selfmessage("PTB: (announce) Announcements are OFF."); } if (streq(Command, "limitjoin") && strlen(Argument)) option_limitjoin = check_param(Argument); if (streq(Command, "status") || streq(Command, "limitjoin")) { if (option_limitjoin) selfmessage("PTB: (limitjoin) WTJ prevention is ON."); else selfmessage("PTB: (limitjoin) WTJ prevention is OFF."); } if (streq(Command, "kick") && strlen(Argument)) option_kick = check_param(Argument); if (streq(Command, "status") || streq(Command, "kick")) { if (option_kick) selfmessage("PTB: (kick) Kicking is ON."); else selfmessage("PTB: (kick) Kicking is OFF."); } if (streq(Command, "sayok") && strlen(Argument)) option_sayok = check_param(Argument); if (streq(Command, "status") || streq(Command, "sayok")) { if (option_sayok) selfmessage("PTB: (sayok) ^"OK^" announcements are ON."); else selfmessage("PTB: (sayok) ^"OK^" announcements are OFF."); } if (streq(Command, "savewtj") && strlen(Argument)) option_savewtj = check_param(Argument); if (streq(Command, "status") || streq(Command, "savewtj")) { if (option_savewtj) selfmessage("PTB: (savewtj) Saving to wtj.txt is ON."); else selfmessage("PTB: (savewtj) Saving to wtj.txt is OFF."); } if (streq(Command, "deadonly") && strlen(Argument)) option_deadonly = check_param(Argument); if (streq(Command, "status") || streq(Command, "deadonly")) { if (option_deadonly) selfmessage("PTB: (deadonly) Switching dead only is ON."); else selfmessage("PTB: (deadonly) Switching dead only is OFF."); } if (streq(Command, "maxstreak") && strlen(Argument)) { option_maxstreak = strtonum(Argument); if (option_maxstreak < 1) option_maxstreak = MAX_STREAK; } if (streq(Command, "status") || streq(Command, "maxstreak")) { snprintf(s, MAX_TEXT_LENGTH, "PTB: (maxstreak) Maximum accepted win streak is %d.", option_maxstreak); selfmessage(s); } if (streq(Command, "maxrandom") && strlen(Argument)) { option_maxrandom = strtonum(Argument); if (option_maxrandom < 1) option_maxrandom = MAX_RANDOM; } if (streq(Command, "status") || streq(Command, "maxrandom")) { snprintf(s, MAX_TEXT_LENGTH, "PTB: (maxrandom) Maximum switch randomization is %d.", option_maxrandom); selfmessage(s); } if (streq(Command, "maxrating") && strlen(Argument)) { option_maxrating = fixedstr(Argument); if (option_maxrating <= fixed(1)) option_maxrating = fixedstr(MAX_RATING); } if (streq(Command, "status") || streq(Command, "maxrating")) { snprintf(s, MAX_TEXT_LENGTH, "PTB: (maxrating) Maximum strength rating is %d.%d.", fround(option_maxrating, fround_floor), fround(fmul(fixed(10), ffract(option_maxrating)), fround_floor) ); selfmessage(s); } if (streq(Command, "minrating") && strlen(Argument)) { option_minrating = fixedstr(Argument); if (option_minrating <= fixed(1)) option_minrating = fixedstr(MIN_RATING); } if (streq(Command, "status") || streq(Command, "minrating")) { snprintf(s, MAX_TEXT_LENGTH, "PTB: (minrating) Minimum strength rating is %d.%d.", fround(option_minrating, fround_floor), fround(fmul(fixed(10), ffract(option_minrating)), fround_floor) ); selfmessage(s); } if (streq(Command, "status")) { selfmessage("PTB: To change or view a single setting, type: ^"admin_ptb <setting> <^"on^"|^"off^"|value|^"^">"); } return PLUGIN_HANDLED; } stock displayStatistics(toLog = false) { //say("displayStatistics"); new text[MAX_TEXT_LENGTH]; // team sizes snprintf(text, MAX_TEXT_LENGTH, "PTB: Team sizes: CTs %d, Ts %d", teamCounts[CTS], teamCounts[TS]); if (toLog) log(text); else selfmessage(text); // team scores snprintf(text, MAX_TEXT_LENGTH, "PTB: Team scores: CTs %d, Ts %d", teamScores[CTS], teamScores[TS]); if (toLog) log(text); else selfmessage(text); // Kills:Deaths snprintf(text, MAX_TEXT_LENGTH, "PTB: Team kills:deaths: CTs %d:%d, Ts %d:%d", teamKills[CTS], teamDeaths[CTS], teamKills[TS], teamDeaths[TS]); if (toLog) log(text); else selfmessage(text); // Kills/Deaths snprintf(text, MAX_TEXT_LENGTH, "PTB: Team kills/deaths: CTs %d.%d, Ts %d.%d", fround(ctKD, fround_floor), fround(fmul(fixed(100), ffract(ctKD)), fround_floor), fround(tKD, fround_floor), fround(fmul(fixed(100), ffract(tKD)), fround_floor) ); if (toLog) log(text); else selfmessage(text); // strength snprintf(text, MAX_TEXT_LENGTH, "PTB: Team strengths: CTs %d.%d, Ts %d.%d", fround(ctStrength, fround_floor), fround(fmul(fixed(100), ffract(ctStrength)), fround_floor), fround(tStrength, fround_floor), fround(fmul(fixed(100), ffract(tStrength)), fround_floor) ); if (toLog) log(text); else selfmessage(text); // rating snprintf(text, MAX_TEXT_LENGTH, "PTB: Team ratings: CTs %d.%d, Ts %d.%d", fround(ctRating, fround_floor), fround(fmul(fixed(100), ffract(ctRating)), fround_floor), fround(tRating, fround_floor), fround(fmul(fixed(100), ffract(tRating)), fround_floor) ); if (toLog) log(text); else selfmessage(text); // won rounds if (winStreaks[CTS] > 0) { snprintf(text, MAX_TEXT_LENGTH, "PTB: Last %d round(s) won by CTs.", winStreaks[CTS]); if (toLog) log(text); else selfmessage(text); } else if (winStreaks[TS] > 0) { snprintf(text, MAX_TEXT_LENGTH, "PTB: Last %d round(s) won by Ts.", winStreaks[TS]); if (toLog) log(text); else selfmessage(text); } } /* initVariables() { // read the settings from server.cfg new Argument[20]; get_serverinfo("admin_ptb_switch", Argument, 20); if (strlen(Argument)) option_switch = check_param(Argument); get_serverinfo("admin_ptb_announce", Argument, 20); if (strlen(Argument)) option_announce = check_param(Argument); get_serverinfo("admin_ptb_limitjoin", Argument, 20); if (strlen(Argument)) option_limitjoin = check_param(Argument); get_serverinfo("admin_ptb_kick", Argument, 20); if (strlen(Argument)) option_kick = check_param(Argument); get_serverinfo("admin_ptb_sayok", Argument, 20); if (strlen(Argument)) option_sayok = check_param(Argument); get_serverinfo("admin_ptb_savewtj", Argument, 20); if (strlen(Argument)) option_savewtj = check_param(Argument); get_serverinfo("admin_ptb_deadonly", Argument, 20); if (strlen(Argument)) option_deadonly = check_param(Argument); get_serverinfo("admin_ptb_maxstreak", Argument, 20); if (strlen(Argument)) { option_maxstreak = strtonum(Argument); if (option_maxstreak < 1) option_maxstreak = MAX_STREAK; } get_serverinfo("admin_ptb_maxrandom", Argument, 20); if (strlen(Argument)) { option_maxrandom = strtonum(Argument); if (option_maxrandom < 1) option_maxrandom = MAX_RANDOM; } get_serverinfo("admin_ptb_maxrating", Argument, 20); if (strlen(Argument)) { option_maxrating = fixedstr(Argument); if (option_maxrating <= fixed(1)) option_maxrating = fixedstr(MAX_RATING); } get_serverinfo("admin_ptb_minrating", Argument, 20); if (strlen(Argument)) { option_minrating = fixedstr(Argument); if (option_minrating <= fixed(1)) option_minrating = fixedstr(MIN_RATING); } } */ public plugin_connect(HLUserName, HLIP, UserIndex) { //say("plugin_connect"); if ((UserIndex >= 1) && (UserIndex <= MAX_PLAYERS)) { kills[UserIndex] = 0; deaths[UserIndex] = 0; isChoosingTeam[UserIndex] = 1; isBeingTransfered[UserIndex] = 0; playerTeam[UserIndex] = 0; switchedThisRound[UserIndex] = false; wtjCount[UserIndex] = 0; } else { say("PTB: Shouldn't get here, unexpected UserIndex."); } return PLUGIN_CONTINUE; } public plugin_disconnect(HLUserName, UserIndex) { //say("plugin_disconnect"); //new debug[MAX_DATA_LENGTH]; //snprintf(debug, MAX_DATA_LENGTH, "[DEBUG] PTB plugin_disconnect: %d %d", UserIndex, playerTeam[UserIndex]); //log(debug); if ((UserIndex >= 1) && (UserIndex <= MAX_PLAYERS)) { kills[UserIndex] = 0; deaths[UserIndex] = 0; isChoosingTeam[UserIndex] = 0; isBeingTransfered[UserIndex] = 0; if (playerTeam[UserIndex] == TS || playerTeam[UserIndex] == CTS) { teamCounts[playerTeam[UserIndex]] -= 1; } playerTeam[UserIndex] = 0; switchedThisRound[UserIndex] = false; wtjCount[UserIndex] = 0; } else { say("PTB: Shouldn't get here, unexpected UserIndex."); } // redundant team size check teamCounts[CTS] = 0; teamCounts[TS] = 0; teamCounts[0] = 0; for (new i = 1; i <= MAX_PLAYERS; ++i) teamCounts[playerTeam[i]] += 1; //displayStatistics(true); return PLUGIN_CONTINUE; } public plugin_init() { //say("plugin_init"); //initVariables(); // must du this here option_maxrating = fixedstr(MAX_RATING); option_minrating = fixedstr(MIN_RATING); plugin_registerinfo("PTB", "Ptahhotep's Team Balancer", STRING_VERSION); plugin_registercmd("admin_ptb", "admin_ptb", ACCESS_ALL, "admin_ptb <^"on^" | ^"off^" | ^"status^" | ^"^">: Switch Ptahhotep's Team Balancer on or off, get status or statistics."); //plugin_registercmd("admin_transfer", "admin_transfer", ACCESS_BALANCE); //plugin_registercmd("admin_spectator", "admin_spectator", ACCESS_BALANCE); plugin_registercmd("chooseteam", "ChoosingTeam", ACCESS_ALL); plugin_registercmd("menuselect", "MenuSelect", ACCESS_ALL); plugin_registercmd("radio", "NotChoosingTeam", ACCESS_ALL); plugin_registercmd("buy", "NotChoosingTeam", ACCESS_ALL); plugin_registercmd("buyequip", "NotChoosingTeam", ACCESS_ALL); plugin_registercmd("showbriefing", "NotChoosingTeam", ACCESS_ALL); plugin_registercmd("ptb_teamselection", "ptb_teamselection", ACCESS_CONSOLE); plugin_registercmd("ptb_kill", "ptb_kill", ACCESS_CONSOLE); plugin_registercmd("ptb_teamaction", "ptb_teamaction", ACCESS_CONSOLE); plugin_registercmd("ptb_worldaction", "ptb_worldaction", ACCESS_CONSOLE); exec("logd_reg 54 admin_command ptb_teamselection"); exec("logd_reg 57 admin_command ptb_kill"); exec("logd_reg 61 admin_command ptb_teamaction"); exec("logd_reg 62 admin_command ptb_worldaction"); return PLUGIN_CONTINUE; } |
Autor: | NIGHTMARE! [ 27.04.2002, 21:31 ] |
Betreff des Beitrags: | |
Code: plugin_registerinfo("PTB", "Ptahhotep's Team Balancer", STRING_VERSION); plugin_registercmd("admin_ptb", "admin_ptb", ACCESS_ALL, "admin_ptb <^"on^" | ^"off^" | ^"status^" | ^"^">: Switch Ptahhotep's Team Balancer on or off, get status or statistics.");da stehts doch !!! admin_ptb on, off oder status |
Autor: | NIGHTMARE! [ 27.04.2002, 21:33 ] |
Betreff des Beitrags: | Das ist ein ... |
Das ist ein Teambalancer, der nicht nach der Anzahl der Spieler in einem Team, sondern nach den kills und dem skill der spieler ... Ist oft fairer .. ( also z.B. macht der 3 Profis gegen 5 n00bs oda so ... ) |
Seite 1 von 1 | Alle Zeiten sind UTC+01:00 |
Powered by phpBB® Forum Software © phpBB Limited https://www.phpbb.com/ |