Raised This Month: $ Target: $400
 0% 

Team Balencer for AMXX


  
 
 
Thread Tools Display Modes
Prev Previous Post   Next Post Next
Author Message
roguE
New Member
Join Date: Jun 2004
Old 06-02-2004 , 01:39   Team Balencer for AMXX
Reply With Quote #1

I'm having troubles; The balancer works perfectly fine, But it does not show the 'best player' and 'best team'; I was wondering if I have made this wrong- Please let me know if so; Feel free to correct it.

Code:
#include <amxmodx>

new bool:endscore = true
new blockjoining[2]
new scores[2]
new Float:ppower[33]
new Float:tpower[2]
new Float:tempf
new Float:avepower
new playersnum[2]

Float:maxf(Float:a,Float:b)
	return a < b ? b : a

Float:minf(Float:a,Float:b)
	return a < b ? a : b
	
absn(a)
	return a < 0 ? -a : a	
	
public calculate_power(){
	new teams[33], ppl[32], ippl
	new a, b, c , d, e
	new Float:frags
	new Float:deaths
	new transfer = -1
	
	playersnum[0] = playersnum[1] = 0 // reset player num
	tpower[0] = tpower[1] = 0.0 // reset teams power
	avepower = 0.0 // reset averange skill
	blockjoining[ 0 ] = blockjoining[ 1 ] = PLUGIN_CONTINUE // reset blocking
	
	get_players(ppl,ippl)	// get all players in game
	
	/* Get avarange efficiency, player efficiency and team efficiency. */
	for(a=0;a<ippl;++a){ // calculate efficiency for each player
		b = ppl[a]
		c = get_user_team(b) - 1 // in CS the T team has id #1 and CT has id #2
		teams[b] = c // save what index of team the player has		
		if (c!=0&&c!=1) continue		// Spectator
		frags = float(get_user_frags(b))
		deaths = float(get_user_deaths(b))
		tempf = (frags / (deaths ? deaths : 1.0)) + (frags * 0.1)
		ppower[b] = tempf	
		avepower += tempf // add to sum of all efficiencies for avarange calculation
		playersnum[c]++ // increase number of player in that team
		tpower[c] += tempf	// add the player efficiency to team efficiency
	}
	avepower /= float(playersnum[0] + playersnum[1]) // averange efficiency
		
	/* Get best players. */
	new goodlist[2][32]	// array for list of good players
	new goodnum[2] // how many good player the team has
	goodnum[0] = goodnum[1] = 0
	for(a=0;a<ippl;++a){ // sum eff. for each team
		b = ppl[a]
		c = teams[b]
		if (c!=0&&c!=1) continue		// Spectator
		if ( ppower[b] > avepower ){ // if better than avarange then save him to list
			goodlist[c][goodnum[c]] = b
			goodnum[c]++
		}
	}
		
	/* Display score. */
	new Float: cscore = tpower[1]
	new Float: tscore = tpower[0]
	client_print(0,print_chat,"CT %d (%.2f) -- TERRORIST %d (%.2f)",scores[1],cscore,scores[0],tscore)
	
	/* Try to estimate which team is better and announce about it. */
	new Float: winner = maxf(cscore,tscore)
	new Float: looser = minf(cscore,tscore)
	new Float: compratio = winner / looser
		
	/* Determine index of better team (with higher skill ratio). */
	e = (cscore > tscore) ? 1 : 0
	
	if ( compratio >= 6 ){
		blockjoining[ e ] = PLUGIN_HANDLED /* Block joining to the better team. */
		transfer = e /* Save index of better them to switch from. */
		client_print(0,print_chat,"%s team beats %s", e ? "Ct" : "Terrorist", e ? "Terrorists" : "Cts" )
	}
	else if ( compratio >= 4 ){
		blockjoining[ e ] = PLUGIN_HANDLED /* Block joining to the better team. */
		transfer = e	/* Save index of better them to switch from. */	
		client_print(0,print_chat,"%s team seems to be more powerful",e ? "Ct" : "Terrorist" )
	}
	else if ( compratio >= 2 ){
		blockjoining[ e ] = PLUGIN_HANDLED	/* Block joining to the better team. */		
		client_print(0,print_chat,"%s team is slightly better",e ? "Ct" : "Terrorist" )
	}
	else{
		/*Sometimes there is a situation that team is balanced but there are different
		 	numbers of players in each team. If the difference is higher then 1 then transfer someone.
		 	NOTE: That this condition will be never true for mp_limitteams 2.0 (this is now, however
		 	we will leave it for possibly future modifications.)
		 	
		 	e.g, T 6 -- CT 2, the difference is 4 then get the best from T and worst from CT
		 	and transfor them. Yes it won't balance them but make one team a bit better than
		 	second, ppl tend to switch the team following with the best. If team is to
		 	powerful they won't unbalance team more due to team switching block :)		 	
		*/
		if (  absn(playersnum[0] - playersnum[1]) > 1 )
			transfer = (playersnum[0] > playersnum[1]) ? 0 : 1
		client_print(0,print_chat,"Teams are balanced. Terrorists have %d and Cts %d good player(s)",goodnum[0],goodnum[1])
	}
	
	/* Build list of best players for each team and display them. */
	new list[256], name[32]
	c = goodnum[0]
	b = 0
	for(a=0;a<c;++a)	{ // TERRORIST
		d = goodlist[0][a]
		get_user_name(d,name,31)
		b += format(list[b],255-b,"%s, ",name )
	}
	if (c) {
		list[b-2] = 0 // remove ", " from after last name
		client_print(0,print_chat,"In Terrorists good %s: %s",(c==1)?"is":"are",list)
	}
	c = goodnum[1]
	b = 0
	for(a=0;a<c;++a)	{ // CT
		d = goodlist[1][a]
		get_user_name(d,name,31)
		b += format(list[b],255-b,"%s, ",name )
	}
	if (c) {
		list[b-2] = 0
		client_print(0,print_chat,"In Cts good %s: %s",(c==1)?"is":"are",list)
	}	
		
	/* if there is need to switch someone then determine 
	best and worst then switch them. */
	if (transfer != -1){
		new baplayer[2], woplayer[2] 
		new Float:bestalive[2]
		new Float:worstalive[2]
		baplayer[0] = baplayer[1] = 0
		woplayer[0] = woplayer[1] = 0	
		bestalive[0] = bestalive[1] = 0.0
		worstalive[0] = worstalive[1] = 100.0
		for(a=0;a<ippl;++a){ /* For each player. */
			b = ppl[a]
			c = teams[b] /* The team index will put results to proper place. */
			if (c!=0&&c!=1) continue		// Spectator
			if (is_user_alive(b)) continue
			if (bestalive[c] < ppower[b]){ // Get best dead player
				bestalive[c] = ppower[b]
				baplayer[c] = b
			}
			if (worstalive[c] > ppower[b]){ // Get worst dead player
				worstalive[c] = ppower[b]
				woplayer[c] = b
			}
		}

		/* Get the oposite index of team for worst player to transfer. */
		new optransfer = transfer ? 0 : 1
		/* If there is need for transfering the players then switch them. */
		if (baplayer[transfer] && woplayer[optransfer] ){
			if (playersnum[transfer] > 1) // if has more than 1 player then you may transfer him
				transfer_player(baplayer[transfer],transfer ? "1" : "2" )
			if (playersnum[optransfer] > 1) // if has more than 1 player then you may transfer him
				transfer_player(woplayer[optransfer], optransfer ? "1" : "2" )
		}
	}
}

transfer_player(id,key[]){
	new oldone[2]
	oldone[0] = blockjoining[ 0 ]
	oldone[1] = blockjoining[ 1 ]
	blockjoining[ 0 ] = blockjoining[ 1 ] = PLUGIN_CONTINUE
	//set_cvar_float("mp_limitteams",0.0)
	engclient_cmd(id,"chooseteam")
	engclient_cmd(id,"menuselect",key)
	engclient_cmd(id,"menuselect","5")
	client_print(id,print_center,"You have been moved to another team.")
	client_cmd(id,"slot10")
	//set_cvar_float("mp_limitteams",2.0)
	blockjoining[ 0 ] = oldone[0]
	blockjoining[ 1 ] = oldone[1]
}

actAtEndOfRound(){
	if (!PTB_SWITCH) return
	// skip switching for the first few rounds
	if (roundCounter <= PTB_SWITCHAFTER) return
	// honor switch frequency setting
	if (roundCounter - lastSwitchRound < PTB_SWITCHFREQ) return
	// skip switching for a small number of players
	if (get_playersnum() < PTB_SWITCHMIN) return
	say("PTB: Round ended, checking teams.")
	checkTeamBalance()
	if (winnerTeam) {
		sortTeam(CTS)
		sortTeam(TS)
		if (teamCounts[winnerTeam] <= teamCounts[loserTeam])
			doSwitch()
		else if (teamCounts[loserTeam] < teamCounts[winnerTeam]) 
			doTransfer()
	}
}

createValidTargets(theTeam, bool:deadonly) {
	new n = 0
	for (new i = 0; i < teamCounts[theTeam]; ++i) {
		// Dead only condition
		if ( deadonly && is_user_alive(sortedTeams[theTeam][i]) ) continue
		// Already switched or in PTB_PLAYERFREQ time condition
		if ((lastRoundSwitched[sortedTeams[theTeam][i]] == roundCounter) || 
			(roundCounter - lastRoundSwitched[sortedTeams[theTeam][i]] < PTB_PLAYERFREQ))	continue
		sortedValidTargets[theTeam][n++] = sortedTeams[theTeam][i]
	}
	validTargetCounts[theTeam] = n
}

sortTeam(theTeam) {
	// create list of players
	new n = 0, a = get_maxplayers()
	for (new i = 1; i <= a; ++i) {
		// Get only members of specified team
		if (playerTeam[i] != theTeam) continue
		sortedTeams[theTeam][n++] = i
	}
	// do a selection sort
	new swap, count = n
	for (new i = count-1; i > 0; --i){
		for (new k = i-1; k >= 0; --k){
			// compare players (kills better then other or if equal then with less deaths)
			if ( (kills[sortedTeams[theTeam][k]]<kills[sortedTeams[theTeam][i]])
				|| ( (kills[sortedTeams[theTeam][k]]==kills[sortedTeams[theTeam][i]])	&&
				(deaths[sortedTeams[theTeam][k]]>deaths[sortedTeams[theTeam][i]]))) {
				// swap
				swap = sortedTeams[theTeam][k]
				sortedTeams[theTeam][k] = sortedTeams[theTeam][i]
				sortedTeams[theTeam][i] = swap
			}
		}
	}	
}

Float:score(team, toBeAdded=0, toBeRemoved=0){
	new Float:sumKD = 0.0
	new a = get_maxplayers()
	for (new i = 1; i <= a; ++i) {
		if ( (playerTeam[i]!=team&&i!=toBeAdded)	|| (i==toBeRemoved)	) 
			continue
		sumKD += fdivWorkaround(float(kills[i]), float(deaths[i]))
	}
	new Float:strength = float(teamCounts[team])
	if (sumKD) strength *= sumKD
	return strength
}

oSwitch() {
	new text[256]
	//displayStatistics(0,true)
	// don't switch, if at least one team is empty
	if ( teamCounts[winnerTeam] == 0 || teamCounts[loserTeam] == 0 ) {
		copy(text,255, "PTB: Can't switch players, need players in each team.")
		doTypesay(text, 5, 0, 255, 0)
		say(text)
		return
	}
	// don't switch, if winner is alone (RULER!!!)
	if (teamCounts[winnerTeam] == 1) {
		copy(text,255, "PTB: Won't switch players, best player makes the winning team.")
		doTypesay(text, 5, 0, 255, 0)
		say(text)
		return
	}
	// don't switch, if both teams are full
	if (teamCounts[winnerTeam] >= PTB_MAXSIZE && teamCounts[loserTeam] >= PTB_MAXSIZE) {
		copy(text,255, "PTB: Can't switch players, both teams are full.")
		doTypesay(text, 5, 0, 255, 0)
		say(text)
		return
	}
	if (!PTB_DEADONLY || couldNotSwitchCounter > PTB_FORCESWITCH) {
		// choose from random top or bottom x
		createValidTargets(winnerTeam, false)
		createValidTargets(loserTeam, false)

		if (validTargetCounts[winnerTeam] == 0 || validTargetCounts[loserTeam] == 0) {
			++couldNotSwitchCounter		
			copy(text,255, "PTB: Can't switch players, need valid target in each team.")
			doTypesay(text, 5, 0, 255, 0)
			say(text)
			return
		}
	}
	else {
		//say("switch dead")
		createValidTargets(winnerTeam, true)
		createValidTargets(loserTeam, true)

		if (validTargetCounts[winnerTeam] == 0 || validTargetCounts[loserTeam] == 0) {
			if (++couldNotSwitchCounter > PTB_FORCESWITCH) {
				say("PTB: Couldn't switch dead, switching alive.")
				doSwitch()
				return
			}
			copy(text, 255,"PTB: Can't switch players, need valid target in each team.")
			doTypesay(text, 5, 0, 255, 0)
			say(text)
			return
		}
	}

public team_score() {
	set_cvar_float("mp_autoteambalance",0.0)
	set_cvar_float("mp_limitteams",0.0)
	new tid[2]
	read_data(1,tid,1)
	scores[ (tid[0]=='C') ? 1 : 0 ] = read_data(2)
	if ((endscore = !endscore))// Round end
		set_task(1.0,"calculate_power")
}

public team_select(id, key){
	if ( blockjoining[ key ] == PLUGIN_HANDLED ){
		client_print(id,print_center,"Teams are not balanced.^nPlease join to the opposite side.")
		engclient_cmd(id,"chooseteam")
		return PLUGIN_HANDLED
	}
	return PLUGIN_CONTINUE
}

public plugin_init() {
	register_plugin("Simple Team Balancer","0.5","default")
	register_event("TeamScore","team_score","a")
	register_menucmd(register_menuid("Team_Select"),(1<<0)|(1<<1),"team_select")
	register_menucmd(-2,(1<<0)|(1<<1),"team_select")	// VGUI menu
	return PLUGIN_CONTINUE
}

public team_score(){
	new arg[2]
	read_data(1,arg,1)
	teamScores[ ( arg[0] == 'T' ) ? TS : CTS ] = read_data(2)
}

public win_streaks(param[]){
	new winner = param[0]
	new looser = param[1]
	if (winStreaks[winner] < 0) {
		winStreaks[winner] = 1
		winStreaks[looser] = -1
	}
	else {
		winStreaks[winner]++
		winStreaks[looser]--
	}
	actAtEndOfRound()
}

public round_end(){
	new param[12]
	read_data(2,param,8)
	if (param[7]=='c') {//%!MRAD_ctwin
		param[0] = CTS
		param[1] = TS
	}
	else if (param[7]=='t') {//%!MRAD_terwin
		param[0] = TS
		param[1] = CTS
	}
	else
		return // %!MRAD_rounddraw (both teams have left the game)
	set_task(1.5,"win_streaks",0,param,2)
}

public new_round() {
	if ( floatround(get_cvar_float("mp_roundtime") * 60.0) != read_data(1) ) return
	++roundCounter
	announceStatus()
}

// Happen only at team select (also auto-join)
public team_join() {
	new arg[32]
	read_data(3,arg,31)
	lastRoundSwitched[ get_user_index(arg) ] = roundCounter
}

// Can happen at begin of round or team select
public team_assign() {
	new arg[2], team
	new i = read_data(1)	
	read_data(2,arg,1)
	if ( arg[0] == 'C'  )
		team = CTS
	else if ( arg[0] == 'T' )
		team = TS
	else
		team = UNASSIGNED
	teamCounts[playerTeam[i]]-- // Unregister from old team
	teamCounts[team]++ // Increase ammount in new team
	playerTeam[i] = team // Assign to new
}

public game_restart(){
	roundCounter = 0
	lastSwitchRound = 0
	couldNotSwitchCounter = 0
	teamKills[0] = teamKills[1] = teamKills[2] = 0 
	teamDeaths[0] = teamDeaths[1] = teamDeaths[2] = 0
	teamScores[0] = teamScores[1] = teamScores[2] = 0
	winStreaks[0]	= winStreaks[1] = winStreaks[2] = 0
	wtConditions[0] = wtConditions[1] = wtConditions[2] = 0
	validTargetCounts[0] = validTargetCounts[1] = validTargetCounts[2] = 0
	new a = get_maxplayers()
	for (new i = 1; i <= a; ++i){
		kills[i] = 0
		deaths[i] = 0
		wtjCount[i] = 0
		lastRoundSwitched[i] = -999
	}
}

public death_msg(){
	new iWinner = read_data(1)
	new iLoser = read_data(2)
	if ( iWinner < 1 || iWinner > 32 || iLoser < 1 || iLoser > 32 ) 
		return
	if ( playerTeam[iWinner] == playerTeam[iLoser] )
		return // no TKS!!!
	kills[iWinner]++
	deaths[iLoser]++
	if (PTB_SCALEDOWN <= 1) return
	if (kills[iWinner] + deaths[iWinner] >= PTB_MAXINCIDENTS) {
		kills[iWinner] /= PTB_SCALEDOWN
		deaths[iWinner] /= PTB_SCALEDOWN
	}
	if (kills[iLoser] + deaths[iLoser] >= PTB_MAXINCIDENTS) {
		kills[iLoser] /= PTB_SCALEDOWN
		deaths[iLoser] /= PTB_SCALEDOWN
	}
}


if defined CS16_SWITCH
public delay_transfer(args[]) {
	new id = args[0]
	if defined PTB_DEBUG
	og_message("[PTB] Delayed Transfer #%i ('%s',%i)",id,clientVGUIMenu[id],isBeingTransfered[id])
	endif
	if (!isBeingTransfered[id]) return
	user_kill(id,1)
	engclient_cmd(id,"jointeam",(playerTeam[id]==TS) ? "2" : "1")
	engclient_cmd(id,"joinclass","5")
	if (clientVGUIMenu[id][0] != '0') {
		set_user_info( id, "_vgui_menus", clientVGUIMenu[id] )
		clientVGUIMenu[id][0] = '0'
	}
}
Thanks for your time.
roguE is offline
Send a message via AIM to roguE
 



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 14:48.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode