Advertisement
Guest User

Untitled

a guest
Dec 8th, 2013
48
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 44.66 KB | None | 0 0
  1. #include <amxmodx>
  2. #include <amxmisc>
  3. #include <cstrike>
  4.  
  5. // Uncomment for support immunity on VIP
  6. //#define PTB_VIP_IMMUNITY
  7.  
  8. // Uncomment to activate log debug messages.
  9. //#define PTB_DEBUG
  10.  
  11. // team ids
  12. #define UNASSIGNED 0
  13. #define TS 1
  14. #define CTS 2
  15. #define AUTO_TEAM 5
  16.  
  17. new const PTB_VERSION[] = "1.8b3"
  18.  
  19. // team selection control
  20. new bool:PTB_LIMITJOIN = true // set limits on team joining
  21. new PTB_LIMITAFTER = 0 // number of rounds after which teams limiting begins
  22. new PTB_LIMITMIN = 0 // number of minimum players on map for team limiting
  23. new PTB_MAXSIZE = 10 // maximum team size per team
  24. new PTB_MAXDIFF = 2 // maximum team size difference
  25. new PTB_AUTOROUNDS = 3 // number of first rounds into match, which allow autojoin only
  26. new PTB_WTJAUTO = 3 // wtj tries needed to become autojoined
  27. new PTB_WTJKICK = 5 // wtj tries needed to become kicked
  28. new bool:PTB_KICK = true // kick for wtj counts
  29. new bool:PTB_SAVEWTJ = false // save wtjs to wtj.log
  30.  
  31. // team balancing actions
  32. new bool:PTB_SWITCH = true // switch/transfer players
  33. new PTB_SWITCHAFTER = 0 // number of rounds after which switching begins
  34. new PTB_SWITCHMIN = 3 // number of minimum players on map for switching
  35. new PTB_SWITCHFREQ = 1 // relative next possible switch round
  36. new PTB_PLAYERFREQ = 3 // relative next possible switch round for player
  37. new PTB_FORCESWITCH = 3 // number of tries after which PTB switches alive, if neccessary
  38. new bool:PTB_DEADONLY = false // switch dead only
  39.  
  40. // messages
  41. new bool:PTB_TELLWTJ = true // tell about wtj tries
  42. new bool:PTB_ANNOUNCE = true // announce team status at beginning of round
  43. new bool:PTB_SAYOK = true // announce team status, if teams are alright
  44. new bool:PTB_TYPESAY = true // use typesay
  45.  
  46. // team strength limits
  47. new PTB_MAXSTREAK = 2 // max. allowed team win streak
  48. new PTB_MAXSCORE = 2 // max. allowed team score difference
  49. new Float:PTB_MINRATING = 1.5 // minimum critical team rating
  50. new Float:PTB_MAXRATING = 2.0 // maximum critical team rating
  51. new Float:PTB_SUPERRATING = 3.0 // super critical team rating
  52. new PTB_MAXINCIDENTS = 50 // maximum kills + deaths before the score is divided by PTB_SCALEDOWN
  53. new PTB_SCALEDOWN = 2 // divisor for kills and deaths, when PTB_MAXINCIDENTS is reached
  54.  
  55. // sorted player indices are 0-based
  56. new sortedTeams[3][32]
  57. new sortedValidTargets[3][32]
  58. new validTargetCounts[3]
  59.  
  60. new teamKills[3]
  61. new teamDeaths[3]
  62. new teamScores[3]
  63. new winStreaks[3]
  64.  
  65. new wtConditions[3]
  66. new winnerTeam
  67. new loserTeam
  68.  
  69. new Float:ctKD
  70. new Float:tKD
  71. new Float:ctStrength
  72. new Float:tStrength
  73. new Float:ctRating
  74. new Float:tRating
  75.  
  76. // player arrays are 1-based, there is no player 0
  77. new clientVGUIMenu[33][2]
  78. new bool:isBeingTransfered[33]
  79. new playerTeam[33]
  80. new lastRoundSwitched[33]
  81. new wtjCount[33]
  82. new teamCounts[3]
  83. new kills[33]
  84. new deaths[33]
  85.  
  86. new roundCounter
  87. new lastSwitchRound
  88. new couldNotSwitchCounter
  89.  
  90. new lastTeamBalanceCheck[32]
  91.  
  92. //New auto-channeling system in amxmodx 1.70
  93. new g_MyMsgSync
  94.  
  95. // pcvars
  96. new saychat
  97. new transfer_type
  98. new switch_immunity
  99. new limitjoin_immunity
  100. new immunity_level
  101. new access_level
  102. new show_in_hlsw
  103.  
  104. public plugin_init(){
  105. register_plugin("Team Balancer",PTB_VERSION,"Ptahhotep")
  106. register_cvar("amx_ptb_version",PTB_VERSION,FCVAR_SERVER|FCVAR_EXTDLL|FCVAR_UNLOGGED|FCVAR_SPONLY)
  107.  
  108. saychat = register_cvar("ptb_saychat", "1")
  109. transfer_type = register_cvar("ptb_transfer_type", "1")
  110. switch_immunity = register_cvar("ptb_switch_immunity", "1")
  111. limitjoin_immunity = register_cvar("ptb_limitjoin_immunity", "1")
  112. immunity_level = register_cvar("ptb_immunity_level", "o")
  113. access_level = register_cvar("ptb_access_level", "l")
  114. show_in_hlsw = register_cvar("ptb_show_in_hlsw", "1")
  115.  
  116. register_menucmd(register_menuid("Team_Select",1),(1<<0)|(1<<1)|(1<<4),"teamselect")
  117. register_event("ShowMenu","menuclass","b","4&CT_Select","4&Terrorist_Select")
  118. register_clcmd("jointeam","jointeam")
  119. register_clcmd("team_join","team_join")
  120. #if defined PTB_DEBUG
  121. register_clcmd("say /last","check_lasttransfer")
  122. #endif
  123. register_event("SendAudio","round_end","a","2=%!MRAD_terwin","2=%!MRAD_ctwin","2=%!MRAD_rounddraw") // Round End
  124. register_event("TeamScore","team_score","a") // Team Score
  125. register_event("RoundTime", "new_round", "bc") // Round Time
  126. register_event("DeathMsg","death_msg","a") // Kill
  127. register_event("TeamInfo","team_assign","a") // Team Assigment (also UNASSIGNED and SPECTATOR)
  128. register_event("TextMsg","team_join","a","1=1","2&Game_join_te","2&Game_join_ct") // Team Joining
  129. register_event("TextMsg","game_restart","a","1=4","2&#Game_C","2&#Game_w") // Game restart
  130. register_concmd("amx_ptb","admin_ptb",get_access_level_flag(),"- displays PTB options")
  131.  
  132. new configsDir[64]
  133. get_configsdir(configsDir, 63)
  134. server_cmd("exec %s/ptb.cfg", configsDir) // Execute main configuration file
  135.  
  136. //New auto-channeling system in amxmodx 1.70
  137. g_MyMsgSync = CreateHudSyncObj()
  138.  
  139.  
  140. // Init clients VGUI-menu setting
  141. // Set terminating 0 to allow use of char processing instead of string
  142. // to improve performance.
  143. for (new i=0;i<33;i++){
  144. clientVGUIMenu[i][0] = '0'
  145. clientVGUIMenu[i][1] = 0
  146. }
  147.  
  148. return PLUGIN_CONTINUE
  149. }
  150.  
  151. public get_immunity_level_flag()
  152. {
  153. new flags[24]
  154. get_pcvar_string(immunity_level, flags, 23)
  155.  
  156. return(read_flags(flags))
  157. }
  158.  
  159. public get_access_level_flag()
  160. {
  161. new flags[24]
  162. get_pcvar_string(access_level, flags, 23)
  163.  
  164. return(read_flags(flags))
  165. }
  166.  
  167.  
  168. Float:fdivWorkaround(Float:nom, Float:denom){
  169. if ( denom == 0.0) return nom
  170. return floatabs(nom / denom)
  171. }
  172.  
  173. doTypesay(string[], duration, r, g, b) {
  174. if (!PTB_TYPESAY) return
  175. //last parameter is not needed
  176. set_hudmessage(r, g, b, 0.05, 0.25, 0, 6.0, float(duration) , 0.5, 0.15, -1)
  177. //use this instead of show_hudmessage
  178. ShowSyncHudMsg(0, g_MyMsgSync, "%s", string)
  179. }
  180.  
  181. say(string[]){
  182. if(get_pcvar_num(saychat) == 1 || get_pcvar_num(saychat) == 3){
  183. client_print(0,print_chat,string)
  184. server_print(string)
  185. }
  186. }
  187.  
  188. bool:check_param_bool(param[])
  189. return (equali(param, "on") || equal(param, "1")) ? true : false
  190.  
  191. Float:check_param_float(param[],Float:n){
  192. new Float:a = floatstr(param)
  193. if (a < n) a = n
  194. return a
  195. }
  196.  
  197. check_param_num(param[],n){
  198. new a = str_to_num(param)
  199. if (a < n) a = n
  200. return a
  201. }
  202.  
  203. transferPlayer(id){
  204.  
  205. if (!is_user_connected(id)) return
  206. if (isBeingTransfered[id]) return
  207. isBeingTransfered[id] = false
  208.  
  209. new name[32], player_steamid[50], team_pre_transfer[12]
  210. get_user_name(id,name,31)
  211. get_user_authid(id, player_steamid, 49)
  212. get_user_team(id, team_pre_transfer, 11)
  213.  
  214. if(cs_get_user_defuse(id))
  215. cs_set_user_defuse(id, 0);
  216.  
  217. cs_set_user_team(id, (playerTeam[id]==TS) ? 2 : 1)
  218. cs_reset_user_model(id)
  219.  
  220. // This must be done here or lastroundswithed will not be registered
  221. lastRoundSwitched[id] = roundCounter
  222.  
  223. // This logs to hlds logs so Psychostats knows that the player has changed team (PS 3.X)
  224. //"LAntz69<9><STEAM_0:1:1895474><TERRORIST>" joined team "CT" //This is how it will be outputted in hlds logs
  225. log_message("^"%s<%d><%s><%s>^" joined team ^"%s^"",
  226. name, get_user_userid(id), player_steamid, team_pre_transfer, (playerTeam[id]==TS) ? "CT" : "TERRORIST" )
  227.  
  228. if(get_pcvar_num(show_in_hlsw) == 1)
  229. {
  230. // This makes you able to see transfers with HLSW in the chat
  231. log_message("^"<><><>^" triggered ^"amx_chat^" (text ^"[PTB] Transfered %s to %s^")",
  232. name, (playerTeam[id]==TS) ? "CT" : "TERRORIST" )
  233. }
  234.  
  235. #if defined PTB_DEBUG
  236. log_amx("Transfer player: %s lastRoundSwitched[id]: %i roundCounter:%i", name, lastRoundSwitched[id], roundCounter)
  237. client_print(0,print_chat,"Transfer player: %s lastRoundSwitched[id]: %i roundCounter:%i", name, lastRoundSwitched[id], roundCounter)
  238. #endif
  239. }
  240.  
  241. #if defined PTB_DEBUG
  242. public check_lasttransfer(id) {
  243. new lasttransfer, text[255]
  244. lasttransfer = lastRoundSwitched[id]
  245.  
  246. format(text,255,"LastRound transfered: %i", lasttransfer)
  247. say(text)
  248. }
  249. #endif
  250.  
  251. actAtEndOfRound(){
  252. if (!PTB_SWITCH) return
  253. // skip switching for the first few rounds
  254. if (roundCounter <= PTB_SWITCHAFTER) return
  255. // honor switch frequency setting
  256. if (roundCounter - lastSwitchRound < PTB_SWITCHFREQ) return
  257. // skip switching for a small number of players
  258. if (get_playersnum() < PTB_SWITCHMIN) return
  259.  
  260. say("PTB: Round ended, checking teams.")
  261. checkTeamBalance()
  262. if (winnerTeam) {
  263. sortTeam(CTS)
  264. sortTeam(TS)
  265.  
  266. // If they set the cvar(ptb_transfer_type) 1 or less than 2 or bigger than 3
  267. // then standard transfers will be selected
  268. if(get_pcvar_num(transfer_type) < 2 || get_pcvar_num(transfer_type) > 3){
  269.  
  270. // This is the standard if it should be a swith of to players or just one transfer
  271. if (teamCounts[winnerTeam] <= teamCounts[loserTeam]) // Original formula
  272. doSwitch()
  273. else if (teamCounts[loserTeam] < teamCounts[winnerTeam]) // Original formula
  274. doTransfer()
  275.  
  276. }
  277.  
  278. if(get_pcvar_num(transfer_type) == 2){
  279.  
  280. // This is more agressive but not so much as the one below
  281. if (teamCounts[winnerTeam] < teamCounts[loserTeam])
  282. doSwitch()
  283.  
  284. else if (teamCounts[loserTeam] <= teamCounts[winnerTeam])
  285. doTransfer()
  286. }
  287.  
  288. if(get_pcvar_num(transfer_type) == 3){
  289.  
  290. // This is the most agressive transfertype
  291. if ((teamCounts[winnerTeam]+(PTB_MAXDIFF/2)) < teamCounts[loserTeam])
  292. doSwitch()
  293.  
  294. else if (teamCounts[loserTeam] <= (teamCounts[winnerTeam]+(PTB_MAXDIFF/2)))
  295. doTransfer()
  296. }
  297.  
  298. }
  299. }
  300.  
  301. createValidTargets(theTeam, bool:deadonly) {
  302. new n = 0
  303. for (new i = 0; i < teamCounts[theTeam]; ++i) {
  304.  
  305.  
  306. #if defined PTB_VIP_IMMUNITY
  307. // If player is in the VIP team dont touch
  308. if (cs_get_user_vip(sortedTeams[theTeam][i])) continue
  309. #endif
  310.  
  311. // Protection for admins if ptb_switch_immunity 1
  312. if (get_user_flags(sortedTeams[theTeam][i])&get_immunity_level_flag() && (get_pcvar_num(switch_immunity) == 1)) continue
  313. // Dead only condition
  314. if ( deadonly && is_user_alive(sortedTeams[theTeam][i]) ) continue
  315. // Already switched or in PTB_PLAYERFREQ time condition
  316. if ((lastRoundSwitched[sortedTeams[theTeam][i]] == roundCounter) ||
  317. (roundCounter - lastRoundSwitched[sortedTeams[theTeam][i]] < PTB_PLAYERFREQ)) continue
  318. sortedValidTargets[theTeam][n++] = sortedTeams[theTeam][i]
  319. }
  320. validTargetCounts[theTeam] = n
  321. }
  322.  
  323. sortTeam(theTeam) {
  324. // create list of players
  325. new n = 0, a = get_maxplayers()
  326. for (new i = 1; i <= a; ++i) {
  327. // Get only members of specified team
  328. if (playerTeam[i] != theTeam) continue
  329. sortedTeams[theTeam][n++] = i
  330. }
  331. // do a selection sort
  332. new swap, count = n
  333. for (new i = count-1; i > 0; --i){
  334. for (new k = i-1; k >= 0; --k){
  335. // compare players (kills better then other or if equal then with less deaths)
  336. if ( (kills[sortedTeams[theTeam][k]]<kills[sortedTeams[theTeam][i]])
  337. || ( (kills[sortedTeams[theTeam][k]]==kills[sortedTeams[theTeam][i]]) &&
  338. (deaths[sortedTeams[theTeam][k]]>deaths[sortedTeams[theTeam][i]]))) {
  339. // swap
  340. swap = sortedTeams[theTeam][k]
  341. sortedTeams[theTeam][k] = sortedTeams[theTeam][i]
  342. sortedTeams[theTeam][i] = swap
  343. }
  344. }
  345. }
  346. }
  347.  
  348. Float:score(team, toBeAdded=0, toBeRemoved=0){
  349. new Float:sumKD = 0.0
  350. new a = get_maxplayers()
  351. for (new i = 1; i <= a; ++i) {
  352. if ( (playerTeam[i]!=team&&i!=toBeAdded) || (i==toBeRemoved) )
  353. continue
  354. sumKD += fdivWorkaround(float(kills[i]), float(deaths[i]))
  355. }
  356. new Float:strength = float(teamCounts[team])
  357. if (sumKD) strength *= sumKD
  358. return strength
  359. }
  360.  
  361. doSwitch() {
  362. new text[256]
  363. //displayStatistics(0,true)
  364. // don't switch, if at least one team is empty
  365. if ( teamCounts[winnerTeam] == 0 || teamCounts[loserTeam] == 0 ) {
  366. copy(text,255, "PTB: Can't switch players, need players in each team.")
  367. doTypesay(text, 5, 0, 255, 0)
  368. say(text)
  369. return
  370. }
  371. // don't switch, if winner is alone (RULER!!!)
  372. if (teamCounts[winnerTeam] == 1) {
  373. copy(text,255, "PTB: Won't switch players, best player makes the winning team.")
  374. doTypesay(text, 5, 0, 255, 0)
  375. say(text)
  376. return
  377. }
  378. // don't switch, if both teams are full
  379. if (teamCounts[winnerTeam] >= PTB_MAXSIZE && teamCounts[loserTeam] >= PTB_MAXSIZE) {
  380. copy(text,255, "PTB: Can't switch players, both teams are full.")
  381. doTypesay(text, 5, 0, 255, 0)
  382. say(text)
  383. return
  384. }
  385. if (!PTB_DEADONLY || couldNotSwitchCounter > PTB_FORCESWITCH) {
  386. // choose from random top or bottom x
  387. createValidTargets(winnerTeam, false)
  388. createValidTargets(loserTeam, false)
  389.  
  390. if (validTargetCounts[winnerTeam] == 0 || validTargetCounts[loserTeam] == 0) {
  391. ++couldNotSwitchCounter
  392. copy(text,255, "PTB: Can't switch players, need valid target in each team.")
  393. doTypesay(text, 5, 0, 255, 0)
  394. say(text)
  395. return
  396. }
  397. }
  398. else {
  399. //say("switch dead")
  400. createValidTargets(winnerTeam, true)
  401. createValidTargets(loserTeam, true)
  402.  
  403. if (validTargetCounts[winnerTeam] == 0 || validTargetCounts[loserTeam] == 0) {
  404. if (++couldNotSwitchCounter > PTB_FORCESWITCH) {
  405. say("PTB: Couldn't switch dead, switching alive.")
  406. doSwitch()
  407. return
  408. }
  409. copy(text, 255,"PTB: Can't switch players, need valid target in each team.")
  410. doTypesay(text, 5, 0, 255, 0)
  411. say(text)
  412. return
  413. }
  414. }
  415. // Now search through the possible 1 to 1 swaps to equalize the strength as much as possible
  416. new Float:closestScore = floatabs(score(winnerTeam) - score(loserTeam))
  417. new Float:myScore, toLoser, toWinner
  418. new winner = 0
  419. new loser = 0
  420. for (new w = 0; w < validTargetCounts[winnerTeam]; ++w) {
  421. toLoser = sortedValidTargets[winnerTeam][w]
  422. for (new l = 0; l < validTargetCounts[loserTeam]; ++l) {
  423. toWinner = sortedValidTargets[loserTeam][l]
  424. myScore = floatabs(score(winnerTeam, toWinner, toLoser) - score(loserTeam, toLoser, toWinner))
  425. if (myScore < closestScore) {
  426. closestScore = myScore
  427. winner = toLoser
  428. loser = toWinner
  429. }
  430. }
  431. }
  432. if (winner == 0 && loser == 0) {
  433. copy(text, 255,"PTB: No switch would improve team balancing.")
  434. doTypesay(text, 5, 0, 255, 0)
  435. say(text)
  436. return
  437. }
  438. couldNotSwitchCounter = 0
  439. lastSwitchRound = roundCounter
  440. new winnerName[32], loserName[32]
  441. get_user_name(winner,winnerName,31)
  442. get_user_name(loser,loserName,31)
  443. // if one team is full, first move the the player from the full team ...
  444. if (teamCounts[winnerTeam] >= PTB_MAXSIZE){
  445. transferPlayer(winner)
  446. transferPlayer(loser)
  447. }
  448. else {
  449. transferPlayer(loser)
  450. transferPlayer(winner)
  451. }
  452. format(text,255,"PTB: Switching %s with %s.",winnerName,loserName)
  453.  
  454. if(get_pcvar_num(saychat) == 2 || get_pcvar_num(saychat) == 3){
  455. //say(text)
  456. //set_hudmessage(0, 255, 0, 0.05, 0.25, 0, 6.0, 5.0 , 0.5, 0.15, 1)
  457. //show_hudmessage(0, text )
  458. set_hudmessage(0, 255, 0, 0.05, 0.25, 0, 6.0, 5.0 , 0.5, 0.15, -1)
  459. ShowSyncHudMsg(0, g_MyMsgSync, "%s", text)
  460. client_print(0,print_chat,"PTB: Switching %s with %s.",winnerName,loserName)
  461. }else{
  462. doTypesay(text, 5, 0, 255, 0)
  463. client_print(0,print_chat,"PTB: Switching %s with %s.",winnerName,loserName)
  464. //say(text)
  465. }
  466. }
  467.  
  468. doTransfer() {
  469. //displayStatistics(0,true)
  470. new text[256]
  471. if (teamCounts[winnerTeam] == 0) {
  472. copy(text,255, "PTB: Can't switch players, need players in each team.")
  473. doTypesay(text, 5, 0, 255, 0)
  474. say(text)
  475. return
  476. }
  477. if (teamCounts[loserTeam] >= PTB_MAXSIZE) {
  478. copy(text,255, "PTB: Can't transfer player, losing team is full.")
  479. doTypesay(text, 5, 0, 255, 0)
  480. say(text)
  481. return
  482. }
  483. if (!PTB_DEADONLY || couldNotSwitchCounter > PTB_FORCESWITCH) {
  484. createValidTargets(winnerTeam, false)
  485. if (validTargetCounts[winnerTeam] == 0) {
  486. copy(text,255, "PTB: Can't transfer player, no valid target in winning team.")
  487. doTypesay(text, 5, 0, 255, 0)
  488. say(text)
  489. ++couldNotSwitchCounter
  490. return
  491. }
  492. }
  493. else {
  494. //say("switch dead")
  495. createValidTargets(winnerTeam, true)
  496. if (validTargetCounts[winnerTeam] == 0) {
  497. if (++couldNotSwitchCounter > PTB_FORCESWITCH) {
  498. say("PTB: Couldn't transfer dead, transferring alive.")
  499. doTransfer()
  500. return
  501. }
  502. copy(text,255, "PTB: Can't transfer player, no valid target in winning team.")
  503. doTypesay(text, 5, 0, 255, 0)
  504. say(text)
  505. return
  506. }
  507. }
  508. new Float:closestScore = floatabs(score(winnerTeam) - score(loserTeam))
  509. new Float:myScore, toLoser
  510. new winner = 0
  511. for (new w = 0; w < validTargetCounts[winnerTeam]; ++w) {
  512. toLoser = sortedValidTargets[winnerTeam][w]
  513. myScore = floatabs(score(winnerTeam, 0, toLoser) - score(loserTeam, toLoser, 0))
  514. if (myScore < closestScore) {
  515. closestScore = myScore
  516. winner = toLoser
  517. }
  518. }
  519. if (winner == 0) {
  520. copy(text, 255,"PTB: No transfer would improve team balancing.")
  521. doTypesay(text, 5, 0, 255, 0)
  522. say(text)
  523. return
  524. }
  525. couldNotSwitchCounter = 0
  526. new winnerName[32]
  527. get_user_name(winner,winnerName,31)
  528. transferPlayer(winner)
  529. format(text,255,"PTB: Transfering %s to the %s",winnerName, (winnerTeam == CTS) ? "Ts" : "CTs")
  530.  
  531. if(get_pcvar_num(saychat) == 2 || get_pcvar_num(saychat) == 3){
  532. //say(text)
  533. //set_hudmessage(0, 255, 0, 0.05, 0.25, 0, 6.0, 5.0 , 0.5, 0.15, 1)
  534. //show_hudmessage(0, text )
  535. set_hudmessage(0, 255, 0, 0.05, 0.25, 0, 6.0, 5.0 , 0.5, 0.15, -1)
  536. ShowSyncHudMsg(0, g_MyMsgSync, "%s", text)
  537. client_print(0,print_chat,"PTB: Transfering %s to the %s",winnerName, (winnerTeam == CTS) ? "Ts" : "CTs")
  538. }else{
  539. doTypesay(text, 5, 0, 255, 0)
  540. client_print(0,print_chat,"PTB: Transfering %s to the %s",winnerName, (winnerTeam == CTS) ? "Ts" : "CTs")
  541. //say(text)
  542. }
  543. }
  544.  
  545. checkTeamBalance() {
  546.  
  547. get_time("%m/%d/%Y - %H:%M:%S",lastTeamBalanceCheck,31 )
  548. calcTeamScores()
  549. ctStrength = score(CTS)
  550. tStrength = score(TS)
  551. ctRating = fdivWorkaround(ctStrength, tStrength)
  552. tRating = fdivWorkaround(tStrength, ctStrength)
  553. wtConditions[TS] = 0
  554. wtConditions[CTS] = 0
  555.  
  556. // compare scores for unequal rating scores
  557. if (teamScores[TS] - teamScores[CTS] > PTB_MAXSCORE && tRating >= PTB_MINRATING)
  558. wtConditions[TS]++
  559.  
  560. if (teamScores[CTS] - teamScores[TS] > PTB_MAXSCORE && ctRating >= PTB_MINRATING)
  561. wtConditions[CTS]++
  562.  
  563. // check streaks for unequal rating scores
  564. if (winStreaks[TS] > PTB_MAXSTREAK && tRating >= PTB_MINRATING)
  565. wtConditions[TS]++
  566.  
  567. if (winStreaks[CTS] > PTB_MAXSTREAK && ctRating >= PTB_MINRATING)
  568. wtConditions[CTS]++
  569.  
  570. // check ratings
  571. if (tRating >= PTB_MAXRATING)
  572. wtConditions[TS]++
  573.  
  574. if (ctRating >= PTB_MAXRATING)
  575. wtConditions[CTS]++
  576.  
  577.  
  578. // check ratings
  579. if (tRating >= PTB_SUPERRATING)
  580. wtConditions[TS]++
  581.  
  582. if (ctRating >= PTB_SUPERRATING)
  583. wtConditions[CTS]++
  584.  
  585.  
  586. // check team sizes for unequal ratings
  587. if (teamCounts[TS] > teamCounts[CTS] && tRating >= PTB_MINRATING)
  588. wtConditions[TS]++
  589.  
  590. if (teamCounts[CTS] > teamCounts[TS] && ctRating >= PTB_MINRATING)
  591. wtConditions[CTS]++
  592.  
  593. // check conditions
  594. if (wtConditions[TS] >= 2) {
  595. winnerTeam = TS
  596. loserTeam = CTS
  597. }
  598. else if (wtConditions[CTS] >= 2) {
  599. winnerTeam = CTS
  600. loserTeam = TS
  601. }
  602. else {
  603. winnerTeam = 0
  604. loserTeam = 0
  605. }
  606. }
  607.  
  608. manageWtjFile(id) {
  609. if (!PTB_SAVEWTJ) return
  610. //say("Trying to write wtj.log ....")
  611. //if (wtjCount[id] < 4) return
  612. //say("wtj.log should be written to now ....")
  613. new text[256], mapname[32], name[32], authid[32]
  614. get_mapname(mapname,31)
  615. get_user_name(id,name,31)
  616. get_user_authid(id,authid,31)
  617. format(text, 255, "%s <%s> %s", name, authid, mapname)
  618. log_to_file("wtj.log", text)
  619. }
  620.  
  621.  
  622. public menuclass(id) {
  623. if (!isBeingTransfered[id]) return PLUGIN_CONTINUE
  624. client_cmd(id,"slot1")
  625. isBeingTransfered[id] = false
  626. return PLUGIN_CONTINUE
  627. }
  628.  
  629. public jointeam(id) {
  630. new arg[2]
  631. read_argv(1,arg,1)
  632. if (isBeingTransfered[id]) return PLUGIN_HANDLED
  633. return checkTeamSwitch(id,str_to_num(arg)) // team is key pressed + 1
  634. }
  635.  
  636. public teamselect(id,key) {
  637.  
  638. return checkTeamSwitch(id,key+1) // team is key pressed + 1
  639. }
  640.  
  641. checkTeamSwitch(id,iNewTeam) {
  642.  
  643. // don't care where player joins
  644. if (!PTB_LIMITJOIN) return PLUGIN_CONTINUE
  645. // Protection for admins if ptb_limitjoin_immunity 1
  646. if (get_user_flags(id)&get_immunity_level_flag() && (get_pcvar_num(limitjoin_immunity) == 1)) return PLUGIN_CONTINUE
  647. // players is transfered so don't care with rest
  648. if (isBeingTransfered[id]) {
  649. //say("TRANSFER")
  650. isBeingTransfered[id] = false
  651. return PLUGIN_CONTINUE
  652. }
  653. //say("NO TRANSFER")
  654. // skip limiting for a few rounds into the map
  655. if (PTB_LIMITAFTER && roundCounter <= PTB_LIMITAFTER) return PLUGIN_CONTINUE
  656. // skip limiting for a small number of players
  657. if (get_playersnum() < PTB_LIMITMIN) return PLUGIN_CONTINUE
  658.  
  659. new iOldTeam = playerTeam[id]
  660.  
  661. // disallow free team choices in the first rounds of a map
  662. if (PTB_AUTOROUNDS && (iOldTeam==UNASSIGNED) && roundCounter<=PTB_AUTOROUNDS && !(get_user_flags(id) & ADMIN_KICK))
  663. iNewTeam = AUTO_TEAM
  664.  
  665. // prevent unwanted rejoining of the same team ...
  666. if (iNewTeam == iOldTeam) {
  667. //say("Preventing rejoining of the same team.")
  668. client_print(id,print_chat,"PTB: Joining to the same team is not allowed...")
  669. #if !defined MANUAL_SWITCH
  670. engclient_cmd(id,"chooseteam") // display menu again
  671. #endif
  672. return PLUGIN_HANDLED
  673. }
  674.  
  675. checkTeamBalance()
  676. //displayStatistics(0,true)
  677.  
  678. // Player for sure was in CT or T team and now is joining to the opposite team
  679. if ((iNewTeam==CTS&&iOldTeam==TS)||(iNewTeam==TS&&iOldTeam==CTS)){
  680. // If someone is in new team and old team weren't full
  681. // and the winning team is a destination team or in
  682. // new team is more players than in old then treat it as wtj
  683. if ( teamCounts[iNewTeam]&&(teamCounts[iOldTeam]<PTB_MAXSIZE)&&
  684. ((iNewTeam==winnerTeam)||(teamCounts[iNewTeam]>=teamCounts[iOldTeam])) ) {
  685. // player is wtjing
  686. new text[256],name[32]
  687. get_user_name(id,name,31)
  688. // Kick wtj player if reached set limit
  689. if (++wtjCount[id] >= PTB_WTJKICK && PTB_KICK) {
  690. format(text, 255, "PTB: Kicking %s for a WTJ count %d of %d.", name, wtjCount[id],PTB_WTJKICK )
  691. doTypesay(text, 5, 0, 255, 0)
  692. say(text)
  693. server_cmd("kick #%d",get_user_userid(id))
  694. return PLUGIN_HANDLED
  695. }
  696. // Announce about WTJ
  697. if (PTB_TELLWTJ) {
  698. if (iNewTeam == CTS) {
  699. format(text, 255, "PTB: The CTs are strong enough, %s (WTJ: %d/%d).", name, wtjCount[id],PTB_WTJKICK)
  700. doTypesay(text, 5, 0, 50, 255)
  701. }
  702. else {
  703. format(text, 255, "PTB: The Ts are strong enough, %s (WTJ: %d/%d).", name, wtjCount[id],PTB_WTJKICK)
  704. doTypesay(text, 5, 255, 50, 0)
  705. }
  706. say(text)
  707. }
  708. #if !defined MANUAL_SWITCH
  709. engclient_cmd(id,"chooseteam") // display menu again
  710. #endif
  711. return PLUGIN_HANDLED
  712. }
  713. // check for maximum team size
  714. if (teamCounts[iNewTeam] >= PTB_MAXSIZE) {
  715. client_print(id,print_chat,"PTB: Maximum team size prohibits team change.")
  716. #if !defined MANUAL_SWITCH
  717. engclient_cmd(id,"chooseteam") // display menu again
  718. #endif
  719. return PLUGIN_HANDLED
  720. }
  721. // check team size difference limits
  722. if ( teamCounts[iNewTeam]+1-teamCounts[iOldTeam] >= PTB_MAXDIFF ) {
  723. client_print(id,print_chat,"PTB: Maximum team size difference prohibits team change.")
  724. #if !defined MANUAL_SWITCH
  725. engclient_cmd(id,"chooseteam") // display menu again
  726. #endif
  727. return PLUGIN_HANDLED
  728. }
  729. return PLUGIN_CONTINUE // OK! He can join to the oppsoite team!!!
  730. }
  731.  
  732. // Player is choosing his team for the first time!
  733. if (iNewTeam==CTS||iNewTeam==TS){
  734. // Get opposite team
  735. new opposingTeam = (iNewTeam==CTS)? TS : CTS
  736. // Players is joining to one team but the opposite is not full
  737. // and his team is bettter then opposite or has more players
  738. if (teamCounts[iNewTeam] && teamCounts[opposingTeam]<PTB_MAXSIZE &&
  739. (iNewTeam==winnerTeam||(!winnerTeam&&teamCounts[iNewTeam]>teamCounts[opposingTeam]))) {
  740. new text[256],name[32]
  741. get_user_name(id,name,31)
  742. if (++wtjCount[id] >= PTB_WTJKICK && PTB_KICK) {
  743. format(text, 255, "PTB: Kicking %s for a WTJ count %d of %d.", name, wtjCount[id],PTB_WTJKICK)
  744. doTypesay(text, 5, 0, 255, 0)
  745. say(text)
  746. server_cmd("kick #%d", get_user_userid(id))
  747. return PLUGIN_HANDLED
  748. }
  749. if (iNewTeam==CTS) {
  750. if (wtjCount[id]>=PTB_WTJAUTO && is_user_connected(id)) {
  751. manageWtjFile(id)
  752. format(text, 255, "PTB: Forcing %s to the Ts (WTJ: %d/%d).", name, wtjCount[id],PTB_WTJKICK)
  753.  
  754. engclient_cmd(id,"jointeam","1")
  755.  
  756. doTypesay(text, 5, 255, 50, 0)
  757. say(text)
  758. }
  759. else if (PTB_TELLWTJ) {
  760. format(text, 255, "PTB: The CTs are strong enough, %s (WTJ: %d/%d).", name, wtjCount[id],PTB_WTJKICK)
  761. doTypesay(text, 5, 0, 50, 255)
  762. say(text)
  763. #if !defined MANUAL_SWITCH
  764. engclient_cmd(id,"chooseteam") // display menu again
  765. #endif
  766. }
  767. }
  768. else {
  769. if (wtjCount[id]>=PTB_WTJAUTO) {
  770. manageWtjFile(id)
  771. format(text, 255, "PTB: Forcing %s to the CTs (WTJ: %d/%d).", name, wtjCount[id],PTB_WTJKICK)
  772.  
  773. engclient_cmd(id,"jointeam","2")
  774.  
  775. doTypesay(text, 5, 0, 50, 255)
  776. say(text)
  777. }
  778. else if (PTB_TELLWTJ) {
  779. format(text, 255, "PTB: The Ts are strong enough, %s (WTJ: %d/%d).", name, wtjCount[id],PTB_WTJKICK)
  780. doTypesay(text, 5, 255, 50, 0)
  781. say(text)
  782. #if !defined MANUAL_SWITCH
  783. engclient_cmd(id,"chooseteam") // display menu again
  784. #endif
  785. }
  786. }
  787. return PLUGIN_HANDLED
  788. }
  789. // check for maximum team size
  790. if (teamCounts[iNewTeam] >= PTB_MAXSIZE) {
  791. client_print(id,print_chat,"PTB: Maximum team size prohibits team join.")
  792. #if !defined MANUAL_SWITCH
  793. engclient_cmd(id,"chooseteam") // display menu again
  794. #endif
  795. return PLUGIN_HANDLED
  796. }
  797. // check team size difference limits
  798. if ( teamCounts[iNewTeam]-teamCounts[opposingTeam] >= PTB_MAXDIFF) {
  799. client_print(id,print_chat,"PTB: Maximum team size difference prohibits team join.")
  800. #if !defined MANUAL_SWITCH
  801. engclient_cmd(id,"chooseteam") // display menu again
  802. #endif
  803. return PLUGIN_HANDLED
  804. }
  805. return PLUGIN_CONTINUE // OK! He can join to the oppsoite team!!!
  806. }
  807.  
  808. // He is choosing the AUTO-SELECT but he was already in game (He wants to play fair!)
  809. if (iNewTeam==AUTO_TEAM&&(iOldTeam==CTS||iOldTeam==TS)) {
  810. //say("Changing team automatically.")
  811. new opposingTeam = (iOldTeam==CTS) ? TS : CTS
  812. if (teamCounts[opposingTeam] && ( (teamCounts[opposingTeam]>=PTB_MAXSIZE)
  813. || (iOldTeam==loserTeam) || (!loserTeam&&teamCounts[iOldTeam]<=teamCounts[opposingTeam])
  814. || (teamCounts[opposingTeam]+1-teamCounts[iOldTeam]>=PTB_MAXDIFF)) ) {
  815. client_print(id,print_chat,"PTB: You have better stay in your current team...")
  816. return PLUGIN_HANDLED
  817. }
  818. client_print(id,print_chat,"PTB: You have been auto-assigned...")
  819.  
  820. engclient_cmd(id,"jointeam",(opposingTeam==CTS)?"2":"1")
  821.  
  822. return PLUGIN_HANDLED
  823. }
  824. // He is choosing the team for the first time with AUTO-SELECT (What a nice kid!)
  825. if (iNewTeam==AUTO_TEAM) {
  826. /* this is the "always smaller team" version
  827. if (teamCounts[CTS] < teamCounts[TS] || teamCounts[TS] >= PTB_MAXSIZE) iNewTeam = CTS
  828. else if (teamCounts[TS] < teamCounts[CTS] || teamCounts[CTS] >= PTB_MAXSIZE) iNewTeam = TS
  829. // both teams have same size ...
  830. else if (winnerTeam && teamCounts[loserTeam]<PTB_MAXSIZE) iNewTeam = loserTeam
  831. else if (teamCounts[TS] >= PTB_MAXSIZE) iNewTeam = CTS
  832. else if (teamCounts[CTS] >= PTB_MAXSIZE) iNewTeam = TS
  833. else iNewTeam = (random_num(0,100) < 50) ? CTS : TS
  834. */
  835. // this version prefers the losing team (but still honors PTB_MAXDIFF)
  836. if (teamCounts[CTS] >= PTB_MAXSIZE) iNewTeam = TS
  837. else if (teamCounts[TS] >= PTB_MAXSIZE) iNewTeam = CTS
  838. else if (teamCounts[CTS]-teamCounts[TS] >= PTB_MAXDIFF) iNewTeam = TS
  839. else if (teamCounts[TS]-teamCounts[CTS] >= PTB_MAXDIFF) iNewTeam = CTS
  840. else if (winnerTeam) iNewTeam = loserTeam
  841. else if (teamCounts[CTS]<teamCounts[TS]) iNewTeam = CTS
  842. else if (teamCounts[TS]<teamCounts[CTS]) iNewTeam = TS
  843. // both teams have same size ...
  844. else iNewTeam = (random_num(0,100) < 50) ? CTS : TS
  845. // check for maximum team size
  846. if (teamCounts[iNewTeam]>=PTB_MAXSIZE) {
  847. client_print(id,print_chat,"PTB: Maximum team size prohibits team join.") // ??? - only a spectator???
  848. #if !defined MANUAL_SWITCH
  849. engclient_cmd(id,"chooseteam") // display menu again
  850. #endif
  851. return PLUGIN_HANDLED
  852. }
  853. client_print(id,print_chat,"PTB: You have been auto-assigned...")
  854.  
  855. engclient_cmd(id,"jointeam",(iNewTeam==CTS)?"2":"1")
  856.  
  857. return PLUGIN_HANDLED
  858. }
  859. return PLUGIN_CONTINUE
  860. }
  861.  
  862. public team_score(){
  863. new arg[2]
  864. read_data(1,arg,1)
  865. teamScores[ ( arg[0] == 'T' ) ? TS : CTS ] = read_data(2)
  866. }
  867.  
  868. public win_streaks(param[]){
  869. new winner = param[0]
  870. new looser = param[1]
  871. if (winStreaks[winner] < 0) {
  872. winStreaks[winner] = 1
  873. winStreaks[looser] = -1
  874. }
  875. else {
  876. winStreaks[winner]++
  877. winStreaks[looser]--
  878. }
  879. actAtEndOfRound()
  880. }
  881.  
  882. public round_end(){
  883. new param[12]
  884. read_data(2,param,8)
  885. if (param[7]=='c') {//%!MRAD_ctwin
  886. param[0] = CTS
  887. param[1] = TS
  888. }
  889. else if (param[7]=='t') {//%!MRAD_terwin
  890. param[0] = TS
  891. param[1] = CTS
  892. }
  893. else
  894. return // %!MRAD_rounddraw (both teams have left the game)
  895. set_task(4.5,"win_streaks",0,param,2)
  896. }
  897.  
  898. public new_round() {
  899. //if ( floatround(get_cvar_float("mp_roundtime") * 60.0) != read_data(1) ) return
  900. if ( floatround(get_cvar_float("mp_roundtime") * 60.0,floatround_floor) != read_data(1) ) return
  901. ++roundCounter
  902. announceStatus()
  903. }
  904.  
  905. // Happen only at team select (also auto-join)
  906. public team_join() {
  907. new arg[32]
  908. read_data(3,arg,31)
  909. lastRoundSwitched[ get_user_index(arg) ] = roundCounter
  910. }
  911.  
  912. // Can happen at begin of round or team select
  913. public team_assign() {
  914. new arg[2], team
  915. new i = read_data(1)
  916. read_data(2,arg,1)
  917. if ( arg[0] == 'C' )
  918. team = CTS
  919. else if ( arg[0] == 'T' )
  920. team = TS
  921. else
  922. team = UNASSIGNED
  923. teamCounts[playerTeam[i]]-- // Unregister from old team
  924. teamCounts[team]++ // Increase ammount in new team
  925. playerTeam[i] = team // Assign to new
  926. }
  927.  
  928. public game_restart(){
  929. roundCounter = 0
  930. lastSwitchRound = 0
  931. couldNotSwitchCounter = 0
  932. teamKills[0] = teamKills[1] = teamKills[2] = 0
  933. teamDeaths[0] = teamDeaths[1] = teamDeaths[2] = 0
  934. teamScores[0] = teamScores[1] = teamScores[2] = 0
  935. winStreaks[0] = winStreaks[1] = winStreaks[2] = 0
  936. wtConditions[0] = wtConditions[1] = wtConditions[2] = 0
  937. validTargetCounts[0] = validTargetCounts[1] = validTargetCounts[2] = 0
  938. new a = get_maxplayers()
  939. for (new i = 1; i <= a; ++i){
  940. kills[i] = 0
  941. deaths[i] = 0
  942. wtjCount[i] = 0
  943. lastRoundSwitched[i] = -999
  944. }
  945. }
  946.  
  947. public death_msg(){
  948. new iWinner = read_data(1)
  949. new iLoser = read_data(2)
  950. if ( iWinner < 1 || iWinner > 32 || iLoser < 1 || iLoser > 32 )
  951. return
  952. if ( playerTeam[iWinner] == playerTeam[iLoser] )
  953. return // no TKS!!!
  954. kills[iWinner]++
  955. deaths[iLoser]++
  956. if (PTB_SCALEDOWN <= 1) return
  957. if (kills[iWinner] + deaths[iWinner] >= PTB_MAXINCIDENTS) {
  958. kills[iWinner] /= PTB_SCALEDOWN
  959. deaths[iWinner] /= PTB_SCALEDOWN
  960. }
  961. if (kills[iLoser] + deaths[iLoser] >= PTB_MAXINCIDENTS) {
  962. kills[iLoser] /= PTB_SCALEDOWN
  963. deaths[iLoser] /= PTB_SCALEDOWN
  964. }
  965. }
  966.  
  967. calcTeamScores() {
  968. teamDeaths[UNASSIGNED] = 0
  969. teamDeaths[CTS] = 0
  970. teamDeaths[TS] = 0
  971. teamKills[UNASSIGNED] = 0
  972. teamKills[CTS] = 0
  973. teamKills[TS] = 0
  974.  
  975. new team, a = get_maxplayers()
  976. for (new i = 1; i <= a; ++i) {
  977. team = playerTeam[i]
  978. teamKills[team] += kills[i]
  979. teamDeaths[team] += deaths[i]
  980. }
  981.  
  982. ctKD = fdivWorkaround(float(teamKills[CTS]), float(teamDeaths[CTS]))
  983. tKD = fdivWorkaround(float(teamKills[TS]), float(teamDeaths[TS]))
  984. }
  985.  
  986. announceStatus() {
  987. if (!PTB_ANNOUNCE) return
  988. checkTeamBalance()
  989. new text[256]
  990. if (winnerTeam == TS) {
  991. format(text, 255, "PTB: The COUNTER-TERRORIST team could use some support.")
  992. doTypesay(text, 5, 0, 50, 255)
  993. say("PTB: The COUNTER-TERRORIST team could use some support.")
  994. }
  995. else if (winnerTeam == CTS) {
  996. format(text, 255, "PTB: The TERRORIST team could use some support.")
  997. doTypesay(text, 5, 255, 50, 0)
  998. say("PTB: The TERRORIST team could use some support.")
  999. }
  1000. else if (wtConditions[TS] > wtConditions[CTS]) {
  1001. format(text, 255, "PTB: Observing TERRORIST team advantage.")
  1002. doTypesay(text, 5, 255, 50, 0)
  1003. say("PTB: Observing TERRORIST team advantage.")
  1004. }
  1005. else if (wtConditions[CTS] > wtConditions[TS]) {
  1006. format(text, 255, "PTB: Observing COUNTER-TERRORIST team advantage.")
  1007. doTypesay(text, 5, 0, 50, 255)
  1008. say("PTB: Observing COUNTER-TERRORIST team advantage.")
  1009. }
  1010. else if (PTB_SAYOK) {
  1011. format(text, 255, "PTB: Teams look fine, no action required.")
  1012. doTypesay(text, 5, 200, 100, 0)
  1013. say("PTB: Teams look fine, no action required.")
  1014. }
  1015. }
  1016.  
  1017. public admin_ptb(id,level,cid) {
  1018. if (!cmd_access(id,level,cid,1))
  1019. return PLUGIN_HANDLED
  1020. new cmd[32], arg[32], lastcmd
  1021.  
  1022. if ( read_argv(1,cmd,31) == 0 ) { // no command - plain amx_ptb
  1023. //console_print(id,"PTB: Ptahhotep's Team Balancer %s", PTB_VERSION)
  1024. //console_print(id,"PTB: (ptahhotep@planethalflife.com)")
  1025. checkTeamBalance()
  1026. displayStatistics(id)
  1027. return PLUGIN_HANDLED
  1028. }
  1029. if (equali(cmd, "on") || equal(cmd, "1")) {
  1030. PTB_LIMITJOIN = true
  1031. PTB_SWITCH = true
  1032. PTB_ANNOUNCE = true
  1033. console_print(id,"PTB: Enabled all PTB actions.")
  1034. return PLUGIN_HANDLED
  1035. }
  1036. if (equali(cmd, "off") || equal(cmd, "0")) {
  1037. PTB_SWITCH = false
  1038. PTB_ANNOUNCE = false
  1039. PTB_LIMITJOIN = false
  1040. console_print(id,"PTB: Disabled all PTB actions.")
  1041. return PLUGIN_HANDLED
  1042. }
  1043. if (equal(cmd, "list") || equal(cmd, "help")) {
  1044. console_print(id,"PTB: Available Commands:")
  1045. console_print(id,"PTB: Team Join Control: ^"limitjoin^", ^"limitafter^", ^"limitmin^", ^"maxsize^", ^"autorounds^",")
  1046. console_print(id,"PTB: ^"maxdiff^", ^"wtjauto^", ^"wtjkick^", ^"kick^", ^"savewtj^"")
  1047. console_print(id,"PTB: Team Balancing Actions: ^"switch^", ^"switchafter^", ^"switchmin^", ^"switchfreq^", ^"playerfreq^",")
  1048. console_print(id,"PTB: ^"forceswitch^", ^"deadonly^"")
  1049. console_print(id,"PTB: Team Strength Limits: ^"maxstreak^", ^"maxscore^", ^"minrating^", ^"maxrating^", ^"superrating^"")
  1050. console_print(id,"PTB: Messages: ^"tellwtj^", ^"announce^", ^"sayok^", ^"typesay^"")
  1051. console_print(id,"PTB: Misc: ^"^", ^"status^", ^"list^", ^"help^", ^"on^", ^"off^", ^"save^", ^"load^"")
  1052. console_print(id,"PTB: To view all PTB settings, type ^"amx_ptb status^".")
  1053. console_print(id,"PTB: To view or change a single PTB setting, type ^"amx_ptb <setting> <on|off|value>^".")
  1054. console_print(id,"PTB: For PTB statistics, simply type ^"amx_ptb^".")
  1055. return PLUGIN_HANDLED
  1056. }
  1057. new arglen = read_argv(2,arg,31)
  1058. new status = equal(cmd, "status")
  1059.  
  1060. // team selection control
  1061. if ( status ) console_print(id,"PTB: ---------- Team Selection Control ----------")
  1062.  
  1063. // PTB_LIMITJOIN
  1064. if ( (lastcmd = equal(cmd, "limitjoin")) && arglen ) PTB_LIMITJOIN = check_param_bool(arg)
  1065. if ( status || lastcmd ) console_print(id,"PTB: (limitjoin) WTJ prevention is %s.", PTB_LIMITJOIN ? "ON" : "OFF")
  1066.  
  1067. // PTB_LIMITAFTER
  1068. if ( (lastcmd = equal(cmd, "limitafter")) && arglen ) PTB_LIMITAFTER = check_param_num(arg,0)
  1069. if ( status || lastcmd ) console_print(id,"PTB: (limitafter) Team limiting starts after %d round(s).", PTB_LIMITAFTER)
  1070.  
  1071. // PTB_LIMITMIN
  1072. if ( (lastcmd = equal(cmd, "limitmin")) && arglen ) PTB_LIMITMIN = check_param_num(arg,0)
  1073. if ( status || lastcmd ) console_print(id,"PTB: (limitmin) Team limiting needs at least %d player(s).", PTB_LIMITMIN)
  1074.  
  1075. // PTB_MAXSIZE
  1076. if ( (lastcmd = equal(cmd, "maxsize")) && arglen ) PTB_MAXSIZE = check_param_num(arg,0)
  1077. if ( status || lastcmd ) console_print(id,"PTB: (maxsize) Maximum team size is %d player(s).", PTB_MAXSIZE)
  1078.  
  1079. // PTB_MAXDIFF
  1080. if ( (lastcmd = equal(cmd, "maxdiff")) && arglen ) PTB_MAXDIFF = check_param_num(arg,1)
  1081. if ( status || lastcmd ) console_print(id,"PTB: (maxdiff) Maximum team size difference is %d.", PTB_MAXDIFF)
  1082.  
  1083. // PTB_AUTOROUNDS
  1084. if ( (lastcmd = equal(cmd, "autorounds")) && arglen ) PTB_AUTOROUNDS = check_param_num(arg,0)
  1085. if ( status || lastcmd ) console_print(id, "PTB: (autorounds) First %d rounds no free team choice.", PTB_AUTOROUNDS)
  1086.  
  1087. // PTB_WTJAUTO
  1088. if ( (lastcmd = equal(cmd, "wtjauto")) && arglen ) PTB_WTJAUTO = check_param_num(arg,0)
  1089. if ( status || lastcmd ) console_print(id,"PTB: (wtjauto) Auto-joining WTJ after %d tr(y/ies).", PTB_WTJAUTO)
  1090.  
  1091. // PTB_WTJKICK
  1092. if ( (lastcmd = equal(cmd, "wtjkick")) && arglen ) PTB_WTJKICK = check_param_num(arg,1)
  1093. if ( status || lastcmd ) console_print(id,"PTB: (wtjauto) Auto-kicking WTJ after %d tr(y/ies).", PTB_WTJKICK)
  1094.  
  1095. // PTB_KICK
  1096. if ( (lastcmd = equal(cmd, "kick")) && arglen ) PTB_KICK = check_param_bool(arg)
  1097. if ( status || lastcmd ) console_print(id,"PTB: (kick) WTJ kicking is %s.", PTB_KICK ? "ON" : "OFF" )
  1098.  
  1099. // PTB_SAVEWTJ
  1100. if ( (lastcmd = equal(cmd, "savewtj")) && arglen ) PTB_SAVEWTJ = check_param_bool(arg)
  1101. if ( status || lastcmd ) console_print(id,"PTB: (savewtj) Saving to wtj.log is %s.", PTB_SAVEWTJ ? "ON" : "OFF");
  1102.  
  1103. // team balancing actions
  1104. if ( status ) console_print(id,"PTB: ---------- Team Balancing Actions ----------")
  1105.  
  1106. // PTB_SWITCH
  1107. if ( (lastcmd = equal(cmd, "switch")) && arglen ) PTB_SWITCH = check_param_bool(arg)
  1108. if ( status || lastcmd ) console_print(id,"PTB: (switch) Team switching is %s.", PTB_SWITCH ? "ON" : "OFF")
  1109.  
  1110. // PTB_SWITCHAFTER
  1111. if ( (lastcmd = equal(cmd, "switchafter")) && arglen ) PTB_SWITCHAFTER = check_param_num(arg,0)
  1112. if ( status || lastcmd ) console_print(id,"PTB: (switchafter) Switching starts after %d round(s).", PTB_SWITCHAFTER)
  1113.  
  1114. // PTB_SWITCHMIN
  1115. if ( (lastcmd = equal(cmd, "switchmin")) && arglen ) PTB_SWITCHMIN = check_param_num(arg,0)
  1116. if ( status || lastcmd ) console_print(id,"PTB: (switchmin) Switching needs at least %d player(s).", PTB_SWITCHMIN)
  1117.  
  1118. // PTB_PLAYERFREQ
  1119. if ( (lastcmd = equal(cmd, "playerfreq")) && arglen ) PTB_PLAYERFREQ = check_param_num(arg,0)
  1120. if ( status || lastcmd ) console_print(id,"PTB: (playerfreq) Individual players are switched every %d round(s) at maximum.", PTB_PLAYERFREQ)
  1121.  
  1122. // PTB_SWITCHFREQ
  1123. if ( (lastcmd = equal(cmd, "switchfreq")) && arglen ) PTB_SWITCHFREQ = check_param_num(arg,1)
  1124. if ( status || lastcmd ) console_print(id,"PTB: (switchfreq) Switch occurs every %d round(s) at maximum.", PTB_SWITCHFREQ)
  1125.  
  1126. // PTB_FORCESWITCH
  1127. if ( (lastcmd = equal(cmd, "forceswitch")) && arglen ) PTB_FORCESWITCH = check_param_num(arg,0)
  1128. if ( status || lastcmd ) console_print(id,"PTB: (forceswitch) Forcing switch after %d unsuccessful switch(es).", PTB_FORCESWITCH)
  1129.  
  1130. // PTB_DEADONLY
  1131. if ( (lastcmd = equal(cmd, "deadonly")) && arglen ) PTB_DEADONLY = check_param_bool(arg)
  1132. if ( status || lastcmd ) console_print(id,"PTB: (deadonly) Switching dead only is %s.",PTB_DEADONLY ? "ON" : "OFF" )
  1133.  
  1134. // messages
  1135. if ( status ) console_print(id,"PTB: ---------- Messages ----------")
  1136.  
  1137. // PTB_TELLWTJ
  1138. if ( (lastcmd = equal(cmd, "tellwtj")) && arglen ) PTB_TELLWTJ = check_param_bool(arg)
  1139. if ( status || lastcmd ) console_print(id,"PTB: (tellwtj) Telling about WTJ tries is %s.",PTB_TELLWTJ ? "ON" : "OFF")
  1140.  
  1141. // PTB_ANNOUNCE
  1142. if ( (lastcmd = equal(cmd, "announce")) && arglen ) PTB_ANNOUNCE = check_param_bool(arg)
  1143. if ( status || lastcmd ) console_print(id,"PTB: (announce) Announcements are %s.",PTB_ANNOUNCE ? "ON" : "OFF")
  1144.  
  1145. // PTB_SAYOK
  1146. if ( (lastcmd = equal(cmd, "sayok")) && arglen ) PTB_SAYOK = check_param_bool(arg)
  1147. if ( status || lastcmd ) console_print(id,"PTB: (sayok) ^"OK^" announcements are %s.",PTB_SAYOK ? "ON" : "OFF")
  1148.  
  1149. // PTB_TYPESAY
  1150. if ( (lastcmd = equal(cmd, "typesay")) && arglen ) PTB_TYPESAY = check_param_bool(arg)
  1151. if ( status || lastcmd ) console_print(id,"PTB: (typesay) typesay usage is %s.",PTB_TYPESAY ? "ON" : "OFF")
  1152.  
  1153. // team strength limits
  1154. if ( status ) console_print(id,"PTB: ---------- Team Strength Limits ----------")
  1155.  
  1156. // PTB_MAXSTREAK
  1157. if ( (lastcmd = equal(cmd, "maxstreak")) && arglen ) PTB_MAXSTREAK = check_param_num(arg,1)
  1158. if ( status || lastcmd ) console_print(id,"PTB: (maxstreak) Maximum accepted win streak is %d.", PTB_MAXSTREAK)
  1159.  
  1160. // PTB_MAXSCORE
  1161. if ( (lastcmd = equal(cmd, "maxscore")) && arglen ) PTB_MAXSCORE = check_param_num(arg,1)
  1162. if ( status || lastcmd ) console_print(id,"PTB: (maxscore) Maximum accepted team score difference is %d.", PTB_MAXSCORE)
  1163.  
  1164. // PTB_MINRATING
  1165. if ( (lastcmd = equal(cmd, "minrating")) && arglen ) PTB_MINRATING = check_param_float(arg,1.0)
  1166. if ( status || lastcmd ) console_print(id,"PTB: (minrating) Minimum critical strength rating is %.2f.",PTB_MINRATING)
  1167.  
  1168. // PTB_MAXRATING
  1169. if ( (lastcmd = equal(cmd, "maxrating")) && arglen ) PTB_MAXRATING = check_param_float(arg,1.0)
  1170. if ( status || lastcmd ) console_print(id,"PTB: (maxrating) Maximum critical strength rating is %.2f.",PTB_MAXRATING)
  1171.  
  1172. // PTB_SUPERRATING
  1173. if ( (lastcmd = equal(cmd, "superrating")) && arglen ) PTB_SUPERRATING = check_param_float(arg,1.0)
  1174. if ( status || lastcmd ) console_print(id,"PTB: (superrating) Super critical strength rating is %.2f.",PTB_SUPERRATING)
  1175.  
  1176. // PTB_MAXINCIDENTS
  1177. if ( (lastcmd = equal(cmd, "maxincidents")) && arglen ) PTB_MAXINCIDENTS = check_param_num(arg,1)
  1178. if ( status || lastcmd ) console_print(id,"PTB: (maxincidents) Maximum incidents before internal player score scale down is %d.", PTB_MAXINCIDENTS)
  1179.  
  1180. // PTB_SCALEDOWN
  1181. if ( (lastcmd = equal(cmd, "scaledown")) && arglen ) PTB_SCALEDOWN = check_param_num(arg,1)
  1182. if ( status || lastcmd ) console_print(id,"PTB: (scaledown) Integer scale down factor for player scores is %d.", PTB_SCALEDOWN)
  1183.  
  1184. // misc
  1185. if ( status ) {
  1186. console_print(id,"PTB: ---------- Misc ----------")
  1187. console_print(id,"PTB: To enable or disable PTB, type ^"admin_ptb <on|1|off|0>^".")
  1188. console_print(id,"PTB: To view or change a single PTB setting, type ^"amx_ptb <setting> <on|off|value>^".")
  1189. console_print(id,"PTB: To view a brief overview of PTB commands, type ^"amx_ptb help^" or ^"amx_ptb list^".")
  1190. console_print(id,"PTB: For PTB statistics, simply type ^"amx_ptb^".")
  1191. }
  1192.  
  1193. return PLUGIN_HANDLED
  1194. }
  1195.  
  1196. stock displayStatistics(id,bool:toLog = false) {
  1197. //say("displayStatistics")
  1198. new text[256]
  1199. // time
  1200. /*format(text, 255, "PTB: Statistics generated at: %s", lastTeamBalanceCheck)
  1201. if (toLog) log_amx(text)
  1202. console_print(id,text)*/
  1203. // connected players
  1204. format(text, 255, "PTB: Connected players: %d", get_playersnum())
  1205. if (toLog) log_amx(text)
  1206. console_print(id,text)
  1207. // team sizes
  1208. format(text, 255, "PTB: Team sizes: CTs %d, Ts %d", teamCounts[CTS], teamCounts[TS])
  1209. if (toLog) log_amx(text)
  1210. console_print(id,text)
  1211. // team scores
  1212. format(text, 255, "PTB: Team scores: CTs %d, Ts %d", teamScores[CTS], teamScores[TS])
  1213. if (toLog) log_amx(text)
  1214. console_print(id,text)
  1215. // Kills:Deaths
  1216. format(text, 255, "PTB: Team kills:deaths: CTs %d:%d, Ts %d:%d", teamKills[CTS], teamDeaths[CTS], teamKills[TS], teamDeaths[TS])
  1217. if (toLog) log_amx(text)
  1218. console_print(id,text)
  1219. // Kills/Deaths
  1220. format(text, 255, "PTB: Team kills/deaths: CTs %.2f, Ts %.2f", ctKD , tKD )
  1221. if (toLog) log_amx(text)
  1222. console_print(id,text)
  1223. // strength
  1224. format(text, 255, "PTB: Team strengths: CTs %.2f, Ts %.2f",ctStrength , tStrength )
  1225. if (toLog) log_amx(text)
  1226. console_print(id,text)
  1227. // rating
  1228. format(text, 255, "PTB: Team ratings: CTs %.2f, Ts %.2f",ctRating,tRating )
  1229. if (toLog) log_amx(text)
  1230. console_print(id,text)
  1231. // won rounds
  1232. if (winStreaks[CTS] > 0) {
  1233. format(text, 255, "PTB: Last %d round(s) won by CTs.", winStreaks[CTS])
  1234. if (toLog) log_amx(text)
  1235. console_print(id,text)
  1236. }
  1237. else if (winStreaks[TS] > 0) {
  1238. format(text, 255, "PTB: Last %d round(s) won by Ts.", winStreaks[TS])
  1239. if (toLog) log_amx(text)
  1240. console_print(id,text)
  1241. }
  1242.  
  1243. // winning team
  1244. switch(winnerTeam){
  1245. case CTS: format(text, 255, "PTB: The CTs are the winning team.")
  1246. case TS: format(text, 255, "PTB: The Ts are the winning team.")
  1247. default: format(text, 255, "PTB: Teams are balanced.")
  1248. }
  1249. if (toLog) log_amx(text)
  1250. console_print(id,text)
  1251.  
  1252. /*format(text, 255, "PTB: These statistics might be already outdated.")
  1253. if (toLog) log_amx(text)
  1254. console_print(id,text)
  1255.  
  1256. format(text, 255, "PTB: To view a brief overview of PTB commands, type ^"amx_ptb help^" or ^"amx_ptb list^".")
  1257. if (toLog) log_amx(text)
  1258. console_print(id,text)
  1259.  
  1260. format(text, 255, "PTB: To view all PTB settings, type ^"amx_ptb status^".")
  1261. if (toLog) log_amx(text)
  1262. console_print(id,text)*/
  1263. }
  1264.  
  1265. public client_connect(id){
  1266. kills[id] = 0
  1267. deaths[id] = 0
  1268. isBeingTransfered[id] = false
  1269. playerTeam[id] = UNASSIGNED
  1270. lastRoundSwitched[id] = -999
  1271. wtjCount[id] = 0
  1272. get_user_info(id,"_vgui_menus",clientVGUIMenu[id],1)
  1273. clientVGUIMenu[id][0] = '0'
  1274.  
  1275. return PLUGIN_CONTINUE
  1276. }
  1277.  
  1278. public client_disconnect(id) {
  1279. kills[id] = 0
  1280. deaths[id] = 0
  1281. isBeingTransfered[id] = false
  1282. playerTeam[id] = UNASSIGNED
  1283. lastRoundSwitched[id] = -999
  1284. wtjCount[id] = 0
  1285. // redundant team size check
  1286. teamCounts[UNASSIGNED] = 0
  1287. teamCounts[CTS] = 0
  1288. teamCounts[TS] = 0
  1289.  
  1290. new a = get_maxplayers()
  1291. for (new i = 1; i <= a; ++i)
  1292. ++teamCounts[playerTeam[i]]
  1293.  
  1294.  
  1295. if (clientVGUIMenu[id][0] != '0') {
  1296. set_user_info( id, "_vgui_menus", clientVGUIMenu[id] )
  1297. clientVGUIMenu[id][0] = '0'
  1298. }
  1299.  
  1300. return PLUGIN_CONTINUE
  1301. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement