diff options
| author | Magnus Auvinen <magnus.auvinen@gmail.com> | 2008-08-14 18:25:44 +0000 |
|---|---|---|
| committer | Magnus Auvinen <magnus.auvinen@gmail.com> | 2008-08-14 18:25:44 +0000 |
| commit | a420eb543f8206730aebb80e60a625f7204694e4 (patch) | |
| tree | 235971d38c917c1b97c512743db64c2fd23ffadc /src/game/server/gamecontroller.cpp | |
| parent | 817f431377c7f1545621ff597c018b133651e991 (diff) | |
| download | zcatch-a420eb543f8206730aebb80e60a625f7204694e4.tar.gz zcatch-a420eb543f8206730aebb80e60a625f7204694e4.zip | |
moved alot of stuff to their own cpp/hpp files
Diffstat (limited to 'src/game/server/gamecontroller.cpp')
| -rw-r--r-- | src/game/server/gamecontroller.cpp | 418 |
1 files changed, 418 insertions, 0 deletions
diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp new file mode 100644 index 00000000..aeab559c --- /dev/null +++ b/src/game/server/gamecontroller.cpp @@ -0,0 +1,418 @@ +/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ +#include <string.h> +#include <engine/e_config.h> +#include <engine/e_server_interface.h> +#include <game/g_mapitems.hpp> +#include "gs_common.hpp" + +#include "entities/pickup.hpp" + +GAMECONTROLLER::GAMECONTROLLER() +{ + // select gametype + if(strcmp(config.sv_gametype, "ctf") == 0) + { + gametype = GAMETYPE_CTF; + dbg_msg("game", "-- Capture The Flag --"); + } + else if(strcmp(config.sv_gametype, "tdm") == 0) + { + gametype = GAMETYPE_TDM; + dbg_msg("game", "-- Team Death Match --"); + } + else + { + gametype = GAMETYPE_DM; + dbg_msg("game", "-- Death Match --"); + } + + // + do_warmup(config.sv_warmup); + game_over_tick = -1; + sudden_death = 0; + round_start_tick = server_tick(); + round_count = 0; + is_teamplay = false; + teamscore[0] = 0; + teamscore[1] = 0; +} + +// UGLY!!!! +extern vec2 spawn_points[3][64]; +extern int num_spawn_points[3]; + +bool GAMECONTROLLER::on_entity(int index, vec2 pos) +{ + int type = -1; + int subtype = 0; + + if(index == ENTITY_SPAWN) + spawn_points[0][num_spawn_points[0]++] = pos; + else if(index == ENTITY_SPAWN_RED) + spawn_points[1][num_spawn_points[1]++] = pos; + else if(index == ENTITY_SPAWN_BLUE) + spawn_points[2][num_spawn_points[2]++] = pos; + else if(index == ENTITY_ARMOR_1) + type = POWERUP_ARMOR; + else if(index == ENTITY_HEALTH_1) + type = POWERUP_HEALTH; + else if(index == ENTITY_WEAPON_SHOTGUN) + { + type = POWERUP_WEAPON; + subtype = WEAPON_SHOTGUN; + } + else if(index == ENTITY_WEAPON_GRENADE) + { + type = POWERUP_WEAPON; + subtype = WEAPON_GRENADE; + } + else if(index == ENTITY_WEAPON_RIFLE) + { + type = POWERUP_WEAPON; + subtype = WEAPON_RIFLE; + } + else if(index == ENTITY_POWERUP_NINJA && config.sv_powerups) + { + type = POWERUP_NINJA; + subtype = WEAPON_NINJA; + } + + if(type != -1) + { + PICKUP *pickup = new PICKUP(type, subtype); + pickup->pos = pos; + return true; + } + + return false; +} + +void GAMECONTROLLER::endround() +{ + if(warmup) // game can't end when we are running warmup + return; + + game.world.paused = true; + game_over_tick = server_tick(); + sudden_death = 0; +} + +void GAMECONTROLLER::resetgame() +{ + game.world.reset_requested = true; +} + +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"; +} + +static bool is_separator(char c) { return c == ';' || c == ' ' || c == ',' || c == '\t'; } + +void GAMECONTROLLER::startround() +{ + resetgame(); + + round_start_tick = server_tick(); + sudden_death = 0; + game_over_tick = -1; + game.world.paused = false; + teamscore[0] = 0; + teamscore[1] = 0; + round_count++; +} + +void GAMECONTROLLER::cyclemap() +{ + if(!strlen(config.sv_maprotation)) + return; + + if(round_count < config.sv_rounds_per_map-1) + return; + + // handle maprotation + const char *map_rotation = config.sv_maprotation; + const char *current_map = config.sv_map; + + int current_map_len = strlen(current_map); + const char *next_map = map_rotation; + while(*next_map) + { + int wordlen = 0; + while(next_map[wordlen] && !is_separator(next_map[wordlen])) + wordlen++; + + if(wordlen == current_map_len && strncmp(next_map, current_map, current_map_len) == 0) + { + // map found + next_map += current_map_len; + while(*next_map && is_separator(*next_map)) + next_map++; + + break; + } + + next_map++; + } + + // restart rotation + if(next_map[0] == 0) + next_map = map_rotation; + + // cut out the next map + char buf[512]; + for(int i = 0; i < 512; i++) + { + buf[i] = next_map[i]; + if(is_separator(next_map[i]) || next_map[i] == 0) + { + buf[i] = 0; + break; + } + } + + // skip spaces + int i = 0; + while(is_separator(buf[i])) + i++; + + dbg_msg("game", "rotating map to %s", &buf[i]); + str_copy(config.sv_map, &buf[i], sizeof(config.sv_map)); +} + +void GAMECONTROLLER::post_reset() +{ + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(game.players[i].client_id != -1) + game.players[i].respawn(); + } +} + +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]; + } + } +} + + +int GAMECONTROLLER::on_character_death(class CHARACTER *victim, class PLAYER *killer, int weapon) +{ + // do scoreing + if(!killer) + return 0; + if(killer == victim->player) + victim->player->score--; // suicide + else + { + if(is_teamplay && victim->team == killer->team) + killer->score--; // teamkill + else + killer->score++; // normal kill + } + return 0; +} + +void GAMECONTROLLER::do_warmup(int seconds) +{ + warmup = seconds*server_tickspeed(); +} + +bool GAMECONTROLLER::is_friendly_fire(int cid1, int cid2) +{ + if(cid1 == cid2) + return false; + + if(is_teamplay) + { + if(game.players[cid1].team == game.players[cid2].team) + return true; + } + + return false; +} + +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(); + } + } + + + // 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].client_id != -1) + prog = max(prog, (game.players[i].score*100)/config.sv_scorelimit); + } + } + } + + if(warmup) + prog = -1; + + server_setbrowseinfo(gametype, prog); +} + +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->gametype = gametype; + + gameobj->warmup = warmup; + + gameobj->teamscore_red = teamscore[0]; + gameobj->teamscore_blue = teamscore[1]; +} + +int GAMECONTROLLER::get_auto_team(int notthisid) +{ + int numplayers[2] = {0,0}; + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(game.players[i].client_id != -1 && game.players[i].client_id != 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; +} + +bool GAMECONTROLLER::can_join_team(int team, int notthisid) +{ + (void)team; + int numplayers[2] = {0,0}; + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(game.players[i].client_id != -1 && game.players[i].client_id != notthisid) + { + if(game.players[i].team >= 0 || game.players[i].team == 1) + numplayers[game.players[i].team]++; + } + } + + return (numplayers[0] + numplayers[1]) < config.sv_max_clients-config.sv_spectator_slots; +} + +void GAMECONTROLLER::do_player_score_wincheck() +{ + if(game_over_tick == -1 && !warmup) + { + // gather some stats + int topscore = 0; + int topscore_count = 0; + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(game.players[i].client_id != -1) + { + if(game.players[i].score > topscore) + { + topscore = game.players[i].score; + topscore_count = 1; + } + else if(game.players[i].score == topscore) + topscore_count++; + } + } + + // check score win condition + if((config.sv_scorelimit > 0 && topscore >= config.sv_scorelimit) || + (config.sv_timelimit > 0 && (server_tick()-round_start_tick) >= config.sv_timelimit*server_tickspeed()*60)) + { + if(topscore_count == 1) + endround(); + else + sudden_death = 1; + } + } +} + +void GAMECONTROLLER::do_team_score_wincheck() +{ + if(game_over_tick == -1 && !warmup) + { + // check score win condition + if((config.sv_scorelimit > 0 && (teamscore[0] >= config.sv_scorelimit || teamscore[1] >= config.sv_scorelimit)) || + (config.sv_timelimit > 0 && (server_tick()-round_start_tick) >= config.sv_timelimit*server_tickspeed()*60)) + { + if(teamscore[0] != teamscore[1]) + endround(); + else + sudden_death = 1; + } + } +} + +int GAMECONTROLLER::clampteam(int team) +{ + if(team < 0) // spectator + return -1; + if(is_teamplay) + return team&1; + return 0; +} + +GAMECONTROLLER *gamecontroller = 0; |