Beispiel #1
0
bool GAMECONTROLLER::can_change_team(PLAYER *pplayer, int jointeam)
{
	int t[2] = {0, 0};
	
	if (!is_teamplay() || jointeam == -1 || !config.sv_teambalance_time)
		return true;
	
	for(int i = 0; i < MAX_CLIENTS; i++)
	{
		PLAYER *p = game.players[i];
		if(p && p->team != -1)
			t[p->team]++;
	}
	
	// simulate what would happen if changed team
	t[jointeam]++;
	if (pplayer->team != -1)
		t[jointeam^1]--;
	
	// there is a player-difference of at least 2
	if(abs(t[0]-t[1]) >= 2)
	{
		// player wants to join team with less players
		if ((t[0] < t[1] && jointeam == 0) || (t[0] > t[1] && jointeam == 1))
			return true;
		else
			return false;
	}
	else
		return true;
}
Beispiel #2
0
bool GAMECONTROLLER::can_spawn(PLAYER *player, vec2 *out_pos)
{
	SPAWNEVAL eval;
	
	// spectators can't spawn
	if(player->team == -1)
		return false;
	
	if(is_teamplay())
	{
		eval.friendly_team = player->team;
		
		// try first try own team spawn, then normal spawn and then enemy
		evaluate_spawn_type(&eval, 1+(player->team&1));
		if(!eval.got)
		{
			evaluate_spawn_type(&eval, 0);
			if(!eval.got)
				evaluate_spawn_type(&eval, 1+((player->team+1)&1));
		}
	}
	else
	{
		evaluate_spawn_type(&eval, 0);
		evaluate_spawn_type(&eval, 1);
		evaluate_spawn_type(&eval, 2);
	}
	
	*out_pos = eval.pos;
	return eval.got;
}
Beispiel #3
0
bool GAMECONTROLLER::check_team_balance()
{
	if(!is_teamplay() || !config.sv_teambalance_time)
		return true;
	
	int t[2] = {0, 0};
	for(int i = 0; i < MAX_CLIENTS; i++)
	{
		PLAYER *p = game.players[i];
		if(p && p->team != -1)
			t[p->team]++;
	}
	
	if(abs(t[0]-t[1]) >= 2)
	{
		dbg_msg("game", "Team is NOT balanced (red=%d blue=%d)", t[0], t[1]);
		if (game.controller->unbalanced_tick == -1)
			game.controller->unbalanced_tick = server_tick();
		return false;
	}
	else
	{
		dbg_msg("game", "Team is balanced (red=%d blue=%d)", t[0], t[1]);
		game.controller->unbalanced_tick = -1;
		return true;
	}
}
Beispiel #4
0
void GAMECONTROLLER::snap(int snapping_client)
{
	NETOBJ_GAME *gameobj = (NETOBJ_GAME *)snap_new_item(NETOBJTYPE_GAME, 0, sizeof(NETOBJ_GAME));
	gameobj->paused = game.world.paused;
	gameobj->game_over = game_over_tick==-1?0:1;
	gameobj->sudden_death = sudden_death;
	
	gameobj->score_limit = config.sv_scorelimit;
	gameobj->time_limit = config.sv_timelimit;
	gameobj->round_start_tick = round_start_tick;
	gameobj->flags = game_flags;
	
	gameobj->warmup = warmup;
	
	gameobj->round_num = (strlen(config.sv_maprotation) && config.sv_rounds_per_map) ? config.sv_rounds_per_map : 0;
	gameobj->round_current = round_count+1;
	
	
	if(snapping_client == -1)
	{
		// we are recording a demo, just set the scores
		gameobj->teamscore_red = teamscore[0];
		gameobj->teamscore_blue = teamscore[1];
	}
	else
	{
		// TODO: this little hack should be removed
		gameobj->teamscore_red = is_teamplay() ? teamscore[0] : game.players[snapping_client]->score;
		gameobj->teamscore_blue = teamscore[1];
	}
}
Beispiel #5
0
int GAMECONTROLLER::clampteam(int team)
{
	if(team < 0) // spectator
		return -1;
	if(is_teamplay())
		return team&1;
	return  0;
}
Beispiel #6
0
void GAMECONTROLLER::on_player_info_change(class PLAYER *p)
{
	const int team_colors[2] = {65387, 10223467};
	if(is_teamplay())
	{
		if(p->team >= 0 || p->team <= 1)
		{
			p->use_custom_color = 1;
			p->color_body = team_colors[p->team];
			p->color_feet = team_colors[p->team];
		}
	}
}
Beispiel #7
0
bool GAMECONTROLLER::is_friendly_fire(int cid1, int cid2)
{
	if(cid1 == cid2)
		return false;
	
	if(is_teamplay())
	{
		if(!game.players[cid1] || !game.players[cid2])
			return false;
			
		if(game.players[cid1]->team == game.players[cid2]->team)
			return true;
	}
	
	return false;
}
Beispiel #8
0
int GAMECONTROLLER::on_character_death(class CHARACTER *victim, class PLAYER *killer, int weapon)
{
	// do scoreing
	if(!killer)
		return 0;
	if(killer == victim->player && (is_race() && config.sv_count_suicide))
		victim->player->score--; // suicide
	else
	{
		if(is_teamplay() && victim->team == killer->team && (is_race() && config.sv_count_teamkill))
			killer->score--; // teamkill
		else if (!is_race() || (is_race() && (config.sv_count_kill || config.sv_count_teamkill)))
			killer->score++; // normal kill
	}
	return 0;
}
Beispiel #9
0
const char *GAMECONTROLLER::get_team_name(int team)
{
	if(is_teamplay())
	{
		if(team == 0)
			return "red team";
		else if(team == 1)
			return "blue team";
	}
	else
	{
		if(team == 0)
			return "game";
	}
	
	return "spectators";
}
Beispiel #10
0
int GAMECONTROLLER::on_character_death(class CHARACTER *victim, class PLAYER *killer, int weapon)
{
	// do scoreing
	if(!killer)
		return 0;
	if(killer == victim->player)
	{
		if(victim->player->logged_in && !victim->player->is_teamchanging)
		{
			victim->player->acc_data.deaths++;
			if(victim->player->acc_data.exp > 0)
				victim->player->acc_data.exp -= 1;
		}
			
		victim->player->score--; // suicide
	}
	else
	{
		if(is_teamplay() && victim->team == killer->team)
		{
			if(killer->logged_in)
				killer->acc_data.betrayals++;
				
			killer->score--; // teamkill
			
			if(victim->player->logged_in)
				victim->player->acc_data.deaths++;
		}
		else
		{
			if(killer->logged_in)
				killer->acc_data.kills++;
				
			killer->score++; // normal kill
			
			if(victim->player->logged_in)
				victim->player->acc_data.deaths++;
		}
	}
	return 0;
}
Beispiel #11
0
int GAMECONTROLLER::get_auto_team(int notthisid)
{
	// this will force the auto balancer to work overtime aswell
	if(config.dbg_stress)
		return 0;
	
	int numplayers[2] = {0,0};
	for(int i = 0; i < MAX_CLIENTS; i++)
	{
		if(game.players[i] && i != notthisid)
		{
			if(game.players[i]->team == 0 || game.players[i]->team == 1)
				numplayers[game.players[i]->team]++;
		}
	}

	int team = 0;
	if(is_teamplay())
		team = numplayers[0] > numplayers[1] ? 1 : 0;
		
	if(can_join_team(team, notthisid))
		return team;
	return -1;
}
Beispiel #12
0
void GAMECONTROLLER::tick()
{
	// do warmup
	if(warmup)
	{
		warmup--;
		if(!warmup)
			startround();
	}
	
	if(game_over_tick != -1)
	{
		// game over.. wait for restart
		if(server_tick() > game_over_tick+server_tickspeed()*10)
		{
			cyclemap();
			startround();
			round_count++;
		}
	}
	
	// do team-balancing
	if (is_teamplay() && unbalanced_tick != -1 && server_tick() > unbalanced_tick+config.sv_teambalance_time*server_tickspeed()*60)
	{
		dbg_msg("game", "Balancing teams");
		
		int t[2] = {0,0};
		int tscore[2] = {0,0};
		for(int i = 0; i < MAX_CLIENTS; i++)
		{
			if(game.players[i] && game.players[i]->team != -1)
			{
				t[game.players[i]->team]++;
				tscore[game.players[i]->team]+=game.players[i]->score;
			}
		}
		
		// are teams unbalanced?
		if(abs(t[0]-t[1]) >= 2)
		{
			int m = (t[0] > t[1]) ? 0 : 1;
			int num_balance = abs(t[0]-t[1]) / 2;
			
			do
			{
				PLAYER *p = 0;
				int pd = tscore[m];
				for(int i = 0; i < MAX_CLIENTS; i++)
				{
					if(!game.players[i])
						continue;
					
					// remember the player who would cause lowest score-difference
					if(game.players[i]->team == m && (!p || abs((tscore[m^1]+game.players[i]->score) - (tscore[m]-game.players[i]->score)) < pd))
					{
						p = game.players[i];
						pd = abs((tscore[m^1]+p->score) - (tscore[m]-p->score));
					}
				}
				
				// move the player to other team without losing his score
				// TODO: change in player::set_team needed: player won't lose score on team-change
				int score_before = p->score;
				p->set_team(m^1);
				p->score = score_before;
				
				p->respawn();
				p->force_balanced = true;
			} while (--num_balance);
			
			force_balanced = true;
		}
		unbalanced_tick = -1;
	}
	
	// update browse info
	int prog = -1;
	if(config.sv_timelimit > 0)
		prog = max(prog, (server_tick()-round_start_tick) * 100 / (config.sv_timelimit*server_tickspeed()*60));

	if(config.sv_scorelimit)
	{
		if(is_teamplay())
		{
			prog = max(prog, (teamscore[0]*100)/config.sv_scorelimit);
			prog = max(prog, (teamscore[1]*100)/config.sv_scorelimit);
		}
		else
		{
			for(int i = 0; i < MAX_CLIENTS; i++)
			{
				if(game.players[i])
					prog = max(prog, (game.players[i]->score*100)/config.sv_scorelimit);
			}
		}
	}

	if(warmup)
		prog = -1;
		
	server_setbrowseinfo(gametype, prog);
}
Beispiel #13
0
void GAMECONTROLLER::tick()
{
	// do info message every 10 minutes
	if(server_tick()%(50*10*60) == 0)
	{
		game.send_chat_target(-1, "-------------------------");
		game.send_chat_target(-1, "Buy Mod - 0.1");
		game.send_chat_target(-1, "by ©Bobynator and ©KaiTee");
		game.send_chat_target(-1, "/cmdlist - see all commands");
		game.send_chat_target(-1, "/info - see aim of the game");
		game.send_chat_target(-1, "-------------------------");
	}

	// inactivity check
	if(!game.world.paused)
		for(int i = 0; i < MAX_CLIENTS; i++)
			if(game.players[i])
				if(server_tick()%server_tickspeed() == 0 && game.players[i]->last_input != -1 && server_tick() - game.players[i]->last_input >= 120 * server_tickspeed())
					if(server_tick() - game.players[i]->last_input >= 120 * server_tickspeed())
					{
						game.players[i]->set_team(-1);  // set him to spectator
						game.send_chat_target(i, "Inactivity Check: Are you still there?");  //portal ftw ;D
					}

	// event stuff
	// TODO: write event over stuff smarter!
	if(slow_tick > 0)
		slow_tick--;
	if(slow_tick == 0)
	{
		console_execute_line("tune_reset");
		slow_tick = -1;
		game.send_broadcast("EVENT OVER!", -1);
	}

	if(speed_tick > 0)
		speed_tick--;
	if(speed_tick == 0)
	{
		console_execute_line("tune_reset");
		speed_tick = -1;
		game.send_broadcast("EVENT OVER!", -1);
	}

	if(x2_tick > 0)
		x2_tick--;
	if(x2_tick == 0)
	{
		x2_tick = -1;
		game.send_broadcast("EVENT OVER!", -1);
	}

	if(one_hit_tick > 0)
		one_hit_tick--;
	if(one_hit_tick == 0)
	{
		one_hit_tick = -1;
		game.send_broadcast("EVENT OVER!", -1);
	}

	if(web_tick > 0)
		web_tick--;
	if(web_tick == 0)
	{
		web_tick = -1;
		game.send_broadcast("EVENT OVER!", -1);
	}

	if(server_tick()%(50*60*60) == 0 && !is_cup)
	{
		int Event = 1+(rand()%(5-1+1));
		if(Event == 1)
			slowmotion(5);
		else if(Event == 2)
			x2(2);
		else if(Event == 3)
			one_hit(1);
		else if(Event == 4)
			speedmotion(3);
		else if(Event == 5)
			spider_web(4);
	}
	
	// do warmup
	if(warmup)
	{
		warmup--;
		if(!warmup)
			startround();
	}

	// do potcount
	int enter_players = 0;
	if(is_cup)
		for(int i = 0; i < MAX_CLIENTS; i++)
			if(game.players[i])
			{
				if(game.players[i]->enter_game == true)
					enter_players++;
			}
	if(potcount < 1 && is_cup && game_over_tick == -1)
	{
		if(server_tick()%(50*6) == 0 && enter_players > 1 && jackpot > 0)
		{
			char buf[512];
			str_format(buf, sizeof(buf), "Jackpot: %d $", jackpot);
			game.send_broadcast(buf, -1, true);
		}
		if(enter_players == 1)
		{
			endround();
		}
	}
	if(potcount > 0 && is_cup)
	{
		potcount--;
		char buf[512];
		str_format(buf, sizeof(buf), "Jackpot: %d $ | Join-Time: %d", jackpot, potcount/50);
		for(int i = 0; i < MAX_CLIENTS; i++)
		{
			if(game.players[i])
			{
				if(game.players[i]->broadcast_count < 1)
					game.send_broadcast(buf, i, true);
			}
		}
	}
	if(potcount == 0 && is_cup)
	{
		if(enter_players >= 2)
		{
			game.send_broadcast("Game Start!", -1);
			resetgame();
			potcount--;
			char buf[512];
			str_format(buf, sizeof(buf), "sv_scorelimit %d", enter_players*5);
			console_execute_line(buf);

			// start game
			round_start_tick = server_tick();
			sudden_death = 0;
			game_over_tick = -1;
			game.world.paused = false;
			teamscore[0] = 0;
			teamscore[1] = 0;
			unbalanced_tick = -1;
			force_balanced = false;
		}
		else
			do_potcount(16);
	}
	
	if(game_over_tick != -1)
	{
		// game over.. wait for restart
		if(server_tick() > game_over_tick+server_tickspeed()*10)
		{
			cyclemap();
			startround();
			round_count++;
		}
	}
	
	// do team-balancing
	if (is_teamplay() && unbalanced_tick != -1 && server_tick() > unbalanced_tick+config.sv_teambalance_time*server_tickspeed()*60)
	{
		dbg_msg("game", "Balancing teams");
		
		int t[2] = {0,0};
		int tscore[2] = {0,0};
		for(int i = 0; i < MAX_CLIENTS; i++)
		{
			if(game.players[i] && game.players[i]->team != -1)
			{
				t[game.players[i]->team]++;
				tscore[game.players[i]->team]+=game.players[i]->score;
			}
		}
		
		// are teams unbalanced?
		if(abs(t[0]-t[1]) >= 2)
		{
			int m = (t[0] > t[1]) ? 0 : 1;
			int num_balance = abs(t[0]-t[1]) / 2;
			
			do
			{
				PLAYER *p = 0;
				int pd = tscore[m];
				for(int i = 0; i < MAX_CLIENTS; i++)
				{
					if(!game.players[i])
						continue;
					
					// remember the player who would cause lowest score-difference
					if(game.players[i]->team == m && (!p || abs((tscore[m^1]+game.players[i]->score) - (tscore[m]-game.players[i]->score)) < pd))
					{
						p = game.players[i];
						pd = abs((tscore[m^1]+p->score) - (tscore[m]-p->score));
					}
				}
				
				// move the player to other team without losing his score
				// TODO: change in player::set_team needed: player won't lose score on team-change
				int score_before = p->score;
				p->set_team(m^1);
				p->score = score_before;
				
				p->respawn();
				p->force_balanced = true;
			} while (--num_balance);
			
			force_balanced = true;
		}
		unbalanced_tick = -1;
	}
	
	// update browse info
	int prog = -1;
	if(config.sv_timelimit > 0)
		prog = max(prog, (server_tick()-round_start_tick) * 100 / (config.sv_timelimit*server_tickspeed()*60));

	if(config.sv_scorelimit)
	{
		if(is_teamplay())
		{
			prog = max(prog, (teamscore[0]*100)/config.sv_scorelimit);
			prog = max(prog, (teamscore[1]*100)/config.sv_scorelimit);
		}
		else
		{
			for(int i = 0; i < MAX_CLIENTS; i++)
			{
				if(game.players[i])
					prog = max(prog, (game.players[i]->score*100)/config.sv_scorelimit);
			}
		}
	}

	if(warmup)
		prog = -1;
		
	server_setbrowseinfo(gametype, prog);
}