diff options
| -rw-r--r-- | src/game/client/game_client.cpp | 86 | ||||
| -rw-r--r-- | src/game/game_protocol.h | 1 | ||||
| -rw-r--r-- | src/game/server/game_server.cpp | 258 | ||||
| -rw-r--r-- | src/game/server/game_server.h | 310 | ||||
| -rw-r--r-- | src/game/server/srv_common.h | 286 | ||||
| -rw-r--r-- | src/game/server/srv_ctf.cpp | 148 | ||||
| -rw-r--r-- | src/game/server/srv_ctf.h | 35 | ||||
| -rw-r--r-- | src/game/server/srv_dm.cpp | 45 | ||||
| -rw-r--r-- | src/game/server/srv_dm.h | 6 | ||||
| -rw-r--r-- | src/game/server/srv_tdm.cpp | 40 | ||||
| -rw-r--r-- | src/game/server/srv_tdm.h | 6 |
11 files changed, 634 insertions, 587 deletions
diff --git a/src/game/client/game_client.cpp b/src/game/client/game_client.cpp index aad2ed27..644d781f 100644 --- a/src/game/client/game_client.cpp +++ b/src/game/client/game_client.cpp @@ -835,11 +835,11 @@ static void render_flag(const obj_flag *prev, const obj_flag *current) gfx_quads_setrotation(angle); vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick()); - float offset = pos.y/32.0f + pos.x/32.0f; - pos.x += cosf(client_localtime()*2.0f+offset)*2.5f; - pos.y += sinf(client_localtime()*2.0f+offset)*2.5f; + + if(current->local_carry) + pos = local_player_pos; - gfx_setcolor(current->team ? 1 : 0,0,current->team ? 0 : 1,1); + gfx_setcolor(current->team ? 0 : 1,0,current->team ? 1 : 0,1); gfx_quads_setsubset( 0, // startx 0, // starty @@ -1532,8 +1532,8 @@ void render_scoreboard(obj_game *gameobj, float x, float y, float w, int team, c title = "Score Board"; } - float tw = gfx_pretty_text_width( 64, "Game Over", -1); - gfx_pretty_text(x+w/2-tw/2, y, 64, "Game Over", -1); + float tw = gfx_pretty_text_width( 64, title, -1); + gfx_pretty_text(x+w/2-tw/2, y, 64, title, -1); y += 64.0f; @@ -1796,7 +1796,6 @@ void render_game() } local_player_pos = mix(predicted_prev_player.pos, predicted_player.pos, client_intrapredtick()); - //local_player_pos = predicted_player.pos; // everything updated, do events if(must_process_events) @@ -1871,39 +1870,52 @@ void render_game() tilemap_render(32.0f, 0); // render items - int num = snap_num_items(SNAP_CURRENT); - for(int i = 0; i < num; i++) { - SNAP_ITEM item; - const void *data = snap_get_item(SNAP_CURRENT, i, &item); - - if(item.type == OBJTYPE_PLAYER) + int num = snap_num_items(SNAP_CURRENT); + for(int i = 0; i < num; i++) { - const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); - if(prev) + SNAP_ITEM item; + const void *data = snap_get_item(SNAP_CURRENT, i, &item); + + if(item.type == OBJTYPE_PROJECTILE) { - client_datas[((const obj_player *)data)->clientid].team = ((const obj_player *)data)->team; - render_player((const obj_player *)prev, (const obj_player *)data); + const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); + if(prev) + render_projectile((const obj_projectile *)prev, (const obj_projectile *)data, item.id); + } + else if(item.type == OBJTYPE_POWERUP) + { + const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); + if(prev) + render_powerup((const obj_powerup *)prev, (const obj_powerup *)data); + } + else if(item.type == OBJTYPE_FLAG) + { + const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); + if (prev) + render_flag((const obj_flag *)prev, (const obj_flag *)data); } } - else if(item.type == OBJTYPE_PROJECTILE) - { - const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); - if(prev) - render_projectile((const obj_projectile *)prev, (const obj_projectile *)data, item.id); - } - else if(item.type == OBJTYPE_POWERUP) - { - const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); - if(prev) - render_powerup((const obj_powerup *)prev, (const obj_powerup *)data); - } - else if(item.type == OBJTYPE_FLAG) + } + + // render players above all + { + int num = snap_num_items(SNAP_CURRENT); + for(int i = 0; i < num; i++) { - const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); - if (prev) - render_flag((const obj_flag *)prev, (const obj_flag *)data); - } + SNAP_ITEM item; + const void *data = snap_get_item(SNAP_CURRENT, i, &item); + + if(item.type == OBJTYPE_PLAYER) + { + const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); + if(prev) + { + client_datas[((const obj_player *)data)->clientid].team = ((const obj_player *)data)->team; + render_player((const obj_player *)prev, (const obj_player *)data); + } + } + } } // render particles @@ -2128,8 +2140,8 @@ void render_game() } else { - render_scoreboard(gameobj, width/2-w-20, 150.0f, w, 0, "Team A"); - render_scoreboard(gameobj, width/2 + 20, 150.0f, w, 1, "Team B"); + render_scoreboard(gameobj, width/2-w-20, 150.0f, w, 0, "Red Team"); + render_scoreboard(gameobj, width/2 + 20, 150.0f, w, 1, "Blue Team"); } } @@ -2179,7 +2191,7 @@ extern "C" void modc_message(int msg) if(msg == MSG_CHAT) { int cid = msg_unpack_int(); - int targets = msg_unpack_int(); + int team = msg_unpack_int(); const char *message = msg_unpack_string(); dbg_msg("message", "chat cid=%d msg='%s'", cid, message); chat_add_line(cid, message); diff --git a/src/game/game_protocol.h b/src/game/game_protocol.h index c21d9301..f7249501 100644 --- a/src/game/game_protocol.h +++ b/src/game/game_protocol.h @@ -144,6 +144,7 @@ struct obj_flag { int x, y; int team; + int local_carry; }; diff --git a/src/game/server/game_server.cpp b/src/game/server/game_server.cpp index 4647318a..0e42614e 100644 --- a/src/game/server/game_server.cpp +++ b/src/game/server/game_server.cpp @@ -2,10 +2,12 @@ #include <stdio.h> #include <string.h> #include <engine/config.h> -#include "../game.h" #include "../version.h" -#include "data.h" #include "game_server.h" +#include "srv_common.h" +#include "srv_ctf.h" +#include "srv_tdm.h" +#include "srv_dm.h" data_container *data = 0x0; @@ -279,8 +281,6 @@ gameobject::gameobject() } // - - // game_over_tick = -1; sudden_death = 0; round_start_tick = server_tick(); @@ -317,174 +317,20 @@ void gameobject::post_reset() } } - - -void gameobject::on_player_spawn(class player *p) -{ -} - void gameobject::on_player_death(class player *victim, class player *killer, int weapon) { - // drop flags - for(int fi = 0; fi < 2; fi++) - { - flag *f = flags[fi]; - if(f && f->carrying_player == victim) - f->carrying_player = 0; - } -} - -void gameobject::tick_ctf() -{ - // do flags - for(int fi = 0; fi < 2; fi++) - { - flag *f = flags[fi]; - - // - if(f->carrying_player) - { - // update flag position - f->pos = f->carrying_player->pos; - - if(gameobj->flags[fi^1]->at_stand) - { - if(distance(f->pos, gameobj->flags[fi^1]->pos) < 24) - { - // CAPTURE! \o/ - for(int i = 0; i < 2; i++) - gameobj->flags[i]->reset(); - } - } - } - else - { - player *players[MAX_CLIENTS]; - int types[] = {OBJTYPE_PLAYER}; - int num = world->find_entities(f->pos, 32.0f, (entity**)players, MAX_CLIENTS, types, 1); - for(int i = 0; i < num; i++) - { - if(players[i]->team == f->team) - { - // return the flag - f->reset(); - } - else - { - // take the flag - f->at_stand = 0; - f->carrying_player = players[i]; - break; - } - } - - if(!f->carrying_player) - { - f->vel.y += gravity; - move_box(&f->pos, &f->vel, vec2(f->phys_size, f->phys_size), 0.5f); - } - } - } -} - -void gameobject::tick_dm() -{ - if(game_over_tick == -1) - { - // game is running - - // gather some stats - int topscore = 0; - int topscore_count = 0; - for(int i = 0; i < MAX_CLIENTS; i++) - { - if(players[i].client_id != -1) - { - if(players[i].score > topscore) - { - topscore = players[i].score; - topscore_count = 1; - } - else if(players[i].score == topscore) - topscore_count++; - } - } - - // check score win condition - if((config.scorelimit > 0 && topscore >= config.scorelimit) || - (config.timelimit > 0 && (server_tick()-round_start_tick) >= config.timelimit*server_tickspeed()*60)) - { - if(topscore_count == 1) - endround(); - else - sudden_death = 1; - } - } + // do scoreing + if(!killer) + return; + if(killer == victim) + victim->score--; // klant arschel else - { - // game over.. wait for restart - if(server_tick() > game_over_tick+server_tickspeed()*10) - startround(); - } + killer->score++; // good shit } -void gameobject::tick_tdm() -{ - if(game_over_tick == -1) - { - // game is running - - // gather some stats - int totalscore[2] = {0,0}; - int topscore_count = 0; - for(int i = 0; i < MAX_CLIENTS; i++) - { - if(players[i].client_id != -1) - totalscore[players[i].team] += players[i].score; - } - if (totalscore[0] >= config.scorelimit) - topscore_count++; - if (totalscore[1] >= config.scorelimit) - topscore_count++; - - // check score win condition - if((config.scorelimit > 0 && (totalscore[0] >= config.scorelimit || totalscore[1] >= config.scorelimit)) || - (config.timelimit > 0 && (server_tick()-round_start_tick) >= config.timelimit*server_tickspeed()*60)) - { - if(topscore_count == 1) - endround(); - else - sudden_death = 1; - } - } - else - { - // game over.. wait for restart - if(server_tick() > game_over_tick+server_tickspeed()*10) - startround(); - } -} void gameobject::tick() { - switch(gametype) - { - case GAMETYPE_CTF: - { - tick_ctf(); - break; - } - case GAMETYPE_TDM: - { - tick_tdm(); - break; - } - default: - { - tick_dm(); - break; - } - } } void gameobject::snap(int snapping_client) @@ -1179,18 +1025,6 @@ bool player::take_damage(vec2 force, int dmg, int from, int weapon) // check for death if(health <= 0) { - // apply score - if(from != -1) - { - if(from == client_id) - score--; - else - { - player *p = get_player(from); - p->score++; - } - } - die(from, weapon); // set attacker's face to happy (taunt!) @@ -1418,55 +1252,6 @@ void powerup::snap(int snapping_client) // POWERUP END /////////////////////// -////////////////////////////////////////////////// -// FLAG -////////////////////////////////////////////////// -flag::flag(int _team) -: entity(OBJTYPE_FLAG) -{ - team = _team; - proximity_radius = phys_size; - carrying_player = 0x0; - - reset(); - - // TODO: should this be done here? - world->insert_entity(this); -} - -void flag::reset() -{ - carrying_player = 0; - at_stand = 1; - pos = stand_pos; - spawntick = -1; -} - -void flag::tick() -{ -} - -bool flag::is_grounded() -{ - if(col_check_point((int)(pos.x+phys_size/2), (int)(pos.y+phys_size/2+5))) - return true; - if(col_check_point((int)(pos.x-phys_size/2), (int)(pos.y+phys_size/2+5))) - return true; - return false; -} - -void flag::snap(int snapping_client) -{ - if(spawntick != -1) - return; - - obj_flag *flag = (obj_flag *)snap_new_item(OBJTYPE_FLAG, id, sizeof(obj_flag)); - flag->x = (int)pos.x; - flag->y = (int)pos.y; - flag->team = team; -} -// FLAG END /////////////////////// - player *get_player(int index) { return &players[index]; @@ -1792,7 +1577,14 @@ void mods_init() world = new game_world; players = new player[MAX_CLIENTS]; - gameobj = new gameobject; + + // select gametype + if(strcmp(config.gametype, "ctf") == 0) + gameobj = new gameobject_ctf; + else if(strcmp(config.gametype, "tdm") == 0) + gameobj = new gameobject_tdm; + else + gameobj = new gameobject_dm; // setup core world for(int i = 0; i < MAX_CLIENTS; i++) @@ -1857,20 +1649,6 @@ void mods_init() if(gameobj->gametype == GAMETYPE_CTF) { - // fetch flagstands - for(int i = 0; i < 2; i++) - { - mapres_flagstand *stand; - stand = (mapres_flagstand *)map_find_item(MAPRES_FLAGSTAND_RED+i, 0); - if(stand) - { - flag *f = new flag(i); - f->stand_pos = vec2(stand->x, stand->y); - f->pos = f->stand_pos; - gameobj->flags[i] = f; - dbg_msg("game", "flag at %f,%f", f->pos.x, f->pos.y); - } - } } world->insert_entity(gameobj); diff --git a/src/game/server/game_server.h b/src/game/server/game_server.h index 22cc1f93..8b137891 100644 --- a/src/game/server/game_server.h +++ b/src/game/server/game_server.h @@ -1,311 +1 @@ -// -class event_handler -{ - static const int MAX_EVENTS = 128; - static const int MAX_DATASIZE = 128*4; - - int types[MAX_EVENTS]; // TODO: remove some of these arrays - int offsets[MAX_EVENTS]; - int sizes[MAX_EVENTS]; - int targets[MAX_EVENTS]; - char data[MAX_DATASIZE]; - - int current_offset; - int num_events; -public: - event_handler(); - void *create(int type, int size, int target = -1); - void clear(); - void snap(int snapping_client); -}; - -extern event_handler events; - -// a basic entity -class entity -{ -private: - friend class game_world; - friend class player; - entity *prev_entity; - entity *next_entity; - - entity *prev_type_entity; - entity *next_type_entity; - - int index; -protected: - int id; - -public: - float proximity_radius; - unsigned flags; - int objtype; - vec2 pos; - - enum - { - FLAG_DESTROY=0x00000001, - FLAG_ALIVE=0x00000002, - }; - - entity(int objtype); - virtual ~entity(); - - virtual void reset() {} - virtual void post_reset() {} - - void set_flag(unsigned flag) { flags |= flag; } - void clear_flag(unsigned flag) { flags &= ~flag; } - - virtual void destroy() { delete this; } - virtual void tick() {} - virtual void tick_defered() {} - - virtual void snap(int snapping_client) {} - - virtual bool take_damage(vec2 force, int dmg, int from, int weapon) { return true; } -}; - - -class game_world -{ - void reset(); - void remove_entities(); -public: - enum - { - NUM_ENT_TYPES=10, // TODO: are more exact value perhaps? :) - }; - - // TODO: two lists seams kinda not good, shouldn't be needed - entity *first_entity; - entity *first_entity_types[NUM_ENT_TYPES]; - bool paused; - bool reset_requested; - - world_core core; - - game_world(); - int find_entities(vec2 pos, float radius, entity **ents, int max); - int find_entities(vec2 pos, float radius, entity **ents, int max, const int* types, int maxtypes); - - void insert_entity(entity *ent); - void destroy_entity(entity *ent); - void remove_entity(entity *ent); - - // - void snap(int snapping_client); - void tick(); -}; - -extern game_world *world; - -// game object -class gameobject : public entity -{ - void resetgame(); - void startround(); - void endround(); - - int round_start_tick; - int game_over_tick; - int sudden_death; - -public: - class flag *flags[2]; - - int gametype; - gameobject(); - virtual void post_reset(); - virtual void tick(); - virtual void tick_dm(); - virtual void tick_tdm(); - virtual void tick_ctf(); - - virtual void on_player_spawn(class player *p); - virtual void on_player_death(class player *victim, class player *killer, int weapon); - - virtual void snap(int snapping_client); - virtual int getteam(int notthisid); -}; - -extern gameobject *gameobj; - - -// TODO: move to seperate file -class powerup : public entity -{ -public: - static const int phys_size = 14; - - int type; - int subtype; // weapon type for instance? - int spawntick; - powerup(int _type, int _subtype = 0); - - virtual void reset(); - virtual void tick(); - virtual void snap(int snapping_client); -}; - - - -// projectile entity -class projectile : public entity -{ -public: - enum - { - PROJECTILE_FLAGS_EXPLODE = 1 << 0, - - WEAPON_PROJECTILETYPE_GUN = 0, - WEAPON_PROJECTILETYPE_ROCKET = 1, - WEAPON_PROJECTILETYPE_SHOTGUN = 2, - }; - - vec2 vel; - entity *powner; // this is nasty, could be removed when client quits - int lifespan; - int owner; - int type; - int flags; - int damage; - int sound_impact; - int weapon; - int bounce; - float force; - - projectile(int type, int owner, vec2 pos, vec2 vel, int span, entity* powner, - int damage, int flags, float force, int sound_impact, int weapon); - virtual void reset(); - virtual void tick(); - virtual void snap(int snapping_client); -}; - -// player entity -class player : public entity -{ -public: - static const int phys_size = 28; - - enum // what are these? - { - MODIFIER_RETURNFLAGS_OVERRIDEVELOCITY = 1 << 0, - MODIFIER_RETURNFLAGS_OVERRIDEPOSITION = 1 << 1, - MODIFIER_RETURNFLAGS_OVERRIDEGRAVITY = 1 << 2, - }; - - // weapon info - entity* hitobjects[10]; - int numobjectshit; - struct weaponstat - { - int ammoregenstart; - int ammo; - int ammocost; - bool got; - } weapons[NUM_WEAPONS]; - int active_weapon; - int last_weapon; - int reload_timer; - int attack_tick; - - int damage_taken; - - int emote_type; - int emote_stop; - - int last_action; - - // - int client_id; - char name[64]; - - // input - player_input previnput; - player_input input; - int jumped; - - int damage_taken_tick; - - int health; - int armor; - - // ninja - vec2 activationdir; - int ninjaactivationtick; - int extrapowerflags; - int currentcooldown; - int currentactivation; - int currentmovetime; - - // - int score; - int team; - int state; - - bool spawning; - bool dead; - int die_tick; - - // latency calculations - int latency_accum; - int latency_accum_min; - int latency_accum_max; - int latency_avg; - int latency_min; - int latency_max; - - // the player core for the physics - player_core core; - - // - player(); - void init(); - virtual void reset(); - virtual void destroy(); - - void try_respawn(); - void respawn(); - - bool is_grounded(); - - void set_weapon(int w); - - int handle_weapons(); - int handle_ninja(); - - virtual void tick(); - virtual void tick_defered(); - - void die(int killer, int weapon); - - virtual bool take_damage(vec2 force, int dmg, int from, int weapon); - virtual void snap(int snaping_client); -}; - -extern player *players; - -// TODO: move to seperate file -class flag : public entity -{ -public: - static const int phys_size = 14; - player *carrying_player; - vec2 vel; - vec2 stand_pos; - - int team; - int spawntick; - int at_stand; - - flag(int _team); - - bool is_grounded(); - - virtual void reset(); - virtual void tick(); - virtual void snap(int snapping_client); -}; diff --git a/src/game/server/srv_common.h b/src/game/server/srv_common.h new file mode 100644 index 00000000..7b6e7e1e --- /dev/null +++ b/src/game/server/srv_common.h @@ -0,0 +1,286 @@ +#include "../game.h" +#include "data.h" + +// +class event_handler +{ + static const int MAX_EVENTS = 128; + static const int MAX_DATASIZE = 128*4; + + int types[MAX_EVENTS]; // TODO: remove some of these arrays + int offsets[MAX_EVENTS]; + int sizes[MAX_EVENTS]; + int targets[MAX_EVENTS]; + char data[MAX_DATASIZE]; + + int current_offset; + int num_events; +public: + event_handler(); + void *create(int type, int size, int target = -1); + void clear(); + void snap(int snapping_client); +}; + +extern event_handler events; + +// a basic entity +class entity +{ +private: + friend class game_world; + friend class player; + entity *prev_entity; + entity *next_entity; + + entity *prev_type_entity; + entity *next_type_entity; + + int index; +protected: + int id; + +public: + float proximity_radius; + unsigned flags; + int objtype; + vec2 pos; + + enum + { + FLAG_DESTROY=0x00000001, + FLAG_ALIVE=0x00000002, + }; + + entity(int objtype); + virtual ~entity(); + + virtual void reset() {} + virtual void post_reset() {} + + void set_flag(unsigned flag) { flags |= flag; } + void clear_flag(unsigned flag) { flags &= ~flag; } + + virtual void destroy() { delete this; } + virtual void tick() {} + virtual void tick_defered() {} + + virtual void snap(int snapping_client) {} + + virtual bool take_damage(vec2 force, int dmg, int from, int weapon) { return true; } +}; + + +class game_world +{ + void reset(); + void remove_entities(); +public: + enum + { + NUM_ENT_TYPES=10, // TODO: are more exact value perhaps? :) + }; + + // TODO: two lists seams kinda not good, shouldn't be needed + entity *first_entity; + entity *first_entity_types[NUM_ENT_TYPES]; + bool paused; + bool reset_requested; + + world_core core; + + game_world(); + int find_entities(vec2 pos, float radius, entity **ents, int max); + int find_entities(vec2 pos, float radius, entity **ents, int max, const int* types, int maxtypes); + + void insert_entity(entity *ent); + void destroy_entity(entity *ent); + void remove_entity(entity *ent); + + // + void snap(int snapping_client); + void tick(); +}; + +extern game_world *world; + +// game object +// TODO: should change name of this one +class gameobject : public entity +{ +protected: + void resetgame(); + void startround(); + void endround(); + + int round_start_tick; + int game_over_tick; + int sudden_death; + +public: + int gametype; + gameobject(); + virtual void post_reset(); + virtual void tick(); + + virtual void on_player_spawn(class player *p) {} + virtual void on_player_death(class player *victim, class player *killer, int weapon); + + virtual void snap(int snapping_client); + virtual int getteam(int notthisid); +}; + +extern gameobject *gameobj; + + +// TODO: move to seperate file +class powerup : public entity +{ +public: + static const int phys_size = 14; + + int type; + int subtype; // weapon type for instance? + int spawntick; + powerup(int _type, int _subtype = 0); + + virtual void reset(); + virtual void tick(); + virtual void snap(int snapping_client); +}; + +// projectile entity +class projectile : public entity +{ +public: + enum + { + PROJECTILE_FLAGS_EXPLODE = 1 << 0, + + WEAPON_PROJECTILETYPE_GUN = 0, + WEAPON_PROJECTILETYPE_ROCKET = 1, + WEAPON_PROJECTILETYPE_SHOTGUN = 2, + }; + + vec2 vel; + entity *powner; // this is nasty, could be removed when client quits + int lifespan; + int owner; + int type; + int flags; + int damage; + int sound_impact; + int weapon; + int bounce; + float force; + + projectile(int type, int owner, vec2 pos, vec2 vel, int span, entity* powner, + int damage, int flags, float force, int sound_impact, int weapon); + virtual void reset(); + virtual void tick(); + virtual void snap(int snapping_client); +}; + +// player entity +class player : public entity +{ +public: + static const int phys_size = 28; + + enum // what are these? + { + MODIFIER_RETURNFLAGS_OVERRIDEVELOCITY = 1 << 0, + MODIFIER_RETURNFLAGS_OVERRIDEPOSITION = 1 << 1, + MODIFIER_RETURNFLAGS_OVERRIDEGRAVITY = 1 << 2, + }; + + // weapon info + entity* hitobjects[10]; + int numobjectshit; + struct weaponstat + { + int ammoregenstart; + int ammo; + int ammocost; + bool got; + } weapons[NUM_WEAPONS]; + int active_weapon; + int last_weapon; + int reload_timer; + int attack_tick; + + int damage_taken; + + int emote_type; + int emote_stop; + + int last_action; + + // + int client_id; + char name[64]; + + // input + player_input previnput; + player_input input; + int jumped; + + int damage_taken_tick; + + int health; + int armor; + + // ninja + vec2 activationdir; + int ninjaactivationtick; + int extrapowerflags; + int currentcooldown; + int currentactivation; + int currentmovetime; + + // + int score; + int team; + int state; + + bool spawning; + bool dead; + int die_tick; + + // latency calculations + int latency_accum; + int latency_accum_min; + int latency_accum_max; + int latency_avg; + int latency_min; + int latency_max; + + // the player core for the physics + player_core core; + + // + player(); + void init(); + virtual void reset(); + virtual void destroy(); + + void try_respawn(); + void respawn(); + + bool is_grounded(); + + void set_weapon(int w); + + int handle_weapons(); + int handle_ninja(); + + virtual void tick(); + virtual void tick_defered(); + + void die(int killer, int weapon); + + virtual bool take_damage(vec2 force, int dmg, int from, int weapon); + virtual void snap(int snaping_client); +}; + +extern player *players; diff --git a/src/game/server/srv_ctf.cpp b/src/game/server/srv_ctf.cpp new file mode 100644 index 00000000..8f345436 --- /dev/null +++ b/src/game/server/srv_ctf.cpp @@ -0,0 +1,148 @@ +#include "srv_common.h" +#include "srv_ctf.h" + +gameobject_ctf::gameobject_ctf() +{ + // fetch flagstands + for(int i = 0; i < 2; i++) + { + mapres_flagstand *stand; + stand = (mapres_flagstand *)map_find_item(MAPRES_FLAGSTAND_RED+i, 0); + if(stand) + { + flag *f = new flag(i); + f->stand_pos = vec2(stand->x, stand->y); + f->pos = f->stand_pos; + flags[i] = f; + //dbg_msg("game", "flag at %f,%f", f->pos.x, f->pos.y); + } + else + { + // report massive failure + } + } +} + +void gameobject_ctf::on_player_spawn(class player *p) +{ +} + +void gameobject_ctf::on_player_death(class player *victim, class player *killer, int weapon) +{ + // drop flags + for(int fi = 0; fi < 2; fi++) + { + flag *f = flags[fi]; + if(f && f->carrying_player == victim) + f->carrying_player = 0; + } +} + +void gameobject_ctf::tick() +{ + gameobject::tick(); + + // do flags + for(int fi = 0; fi < 2; fi++) + { + flag *f = flags[fi]; + + // + if(f->carrying_player) + { + // update flag position + f->pos = f->carrying_player->pos; + + if(flags[fi^1]->at_stand) + { + if(distance(f->pos, flags[fi^1]->pos) < 24) + { + // CAPTURE! \o/ + for(int i = 0; i < 2; i++) + flags[i]->reset(); + } + } + } + else + { + player *players[MAX_CLIENTS]; + int types[] = {OBJTYPE_PLAYER}; + int num = world->find_entities(f->pos, 32.0f, (entity**)players, MAX_CLIENTS, types, 1); + for(int i = 0; i < num; i++) + { + if(players[i]->team == f->team) + { + // return the flag + f->reset(); + } + else + { + // take the flag + f->at_stand = 0; + f->carrying_player = players[i]; + break; + } + } + + if(!f->carrying_player) + { + f->vel.y += gravity; + move_box(&f->pos, &f->vel, vec2(f->phys_size, f->phys_size), 0.5f); + } + } + } +} + +////////////////////////////////////////////////// +// FLAG +////////////////////////////////////////////////// +flag::flag(int _team) +: entity(OBJTYPE_FLAG) +{ + team = _team; + proximity_radius = phys_size; + carrying_player = 0x0; + + reset(); + + // TODO: should this be done here? + world->insert_entity(this); +} + +void flag::reset() +{ + carrying_player = 0; + at_stand = 1; + pos = stand_pos; + spawntick = -1; +} + +void flag::tick() +{ +} + +bool flag::is_grounded() +{ + if(col_check_point((int)(pos.x+phys_size/2), (int)(pos.y+phys_size/2+5))) + return true; + if(col_check_point((int)(pos.x-phys_size/2), (int)(pos.y+phys_size/2+5))) + return true; + return false; +} + +void flag::snap(int snapping_client) +{ + if(spawntick != -1) + return; + + obj_flag *flag = (obj_flag *)snap_new_item(OBJTYPE_FLAG, id, sizeof(obj_flag)); + flag->x = (int)pos.x; + flag->y = (int)pos.y; + flag->team = team; + + if(carrying_player && carrying_player->client_id == snapping_client) + flag->local_carry = 1; + else + flag->local_carry = 0; +} +// FLAG END /////////////////////// diff --git a/src/game/server/srv_ctf.h b/src/game/server/srv_ctf.h new file mode 100644 index 00000000..70bb7777 --- /dev/null +++ b/src/game/server/srv_ctf.h @@ -0,0 +1,35 @@ + +// game object +class gameobject_ctf : public gameobject +{ +public: + class flag *flags[2]; + + gameobject_ctf(); + virtual void tick(); + + virtual void on_player_spawn(class player *p); + virtual void on_player_death(class player *victim, class player *killer, int weapon); +}; + +// TODO: move to seperate file +class flag : public entity +{ +public: + static const int phys_size = 14; + player *carrying_player; + vec2 vel; + vec2 stand_pos; + + int team; + int spawntick; + int at_stand; + + flag(int _team); + + bool is_grounded(); + + virtual void reset(); + virtual void tick(); + virtual void snap(int snapping_client); +}; diff --git a/src/game/server/srv_dm.cpp b/src/game/server/srv_dm.cpp new file mode 100644 index 00000000..01817262 --- /dev/null +++ b/src/game/server/srv_dm.cpp @@ -0,0 +1,45 @@ +#include <engine/config.h> +#include "srv_common.h" +#include "srv_dm.h" + +void gameobject_dm::tick() +{ + if(game_over_tick == -1) + { + // game is running + + // gather some stats + int topscore = 0; + int topscore_count = 0; + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(players[i].client_id != -1) + { + if(players[i].score > topscore) + { + topscore = players[i].score; + topscore_count = 1; + } + else if(players[i].score == topscore) + topscore_count++; + } + } + + // check score win condition + if((config.scorelimit > 0 && topscore >= config.scorelimit) || + (config.timelimit > 0 && (server_tick()-round_start_tick) >= config.timelimit*server_tickspeed()*60)) + { + if(topscore_count == 1) + endround(); + else + sudden_death = 1; + } + } + else + { + // game over.. wait for restart + if(server_tick() > game_over_tick+server_tickspeed()*10) + startround(); + } +} + diff --git a/src/game/server/srv_dm.h b/src/game/server/srv_dm.h new file mode 100644 index 00000000..b6fc8b62 --- /dev/null +++ b/src/game/server/srv_dm.h @@ -0,0 +1,6 @@ +// game object +class gameobject_dm : public gameobject +{ +public: + virtual void tick(); +}; diff --git a/src/game/server/srv_tdm.cpp b/src/game/server/srv_tdm.cpp new file mode 100644 index 00000000..ca1a5a67 --- /dev/null +++ b/src/game/server/srv_tdm.cpp @@ -0,0 +1,40 @@ +#include <engine/config.h> +#include "srv_common.h" +#include "srv_tdm.h" + +void gameobject_tdm::tick() +{ + if(game_over_tick == -1) + { + // game is running + + // gather some stats + int totalscore[2] = {0,0}; + int topscore_count = 0; + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(players[i].client_id != -1) + totalscore[players[i].team] += players[i].score; + } + if (totalscore[0] >= config.scorelimit) + topscore_count++; + if (totalscore[1] >= config.scorelimit) + topscore_count++; + + // check score win condition + if((config.scorelimit > 0 && (totalscore[0] >= config.scorelimit || totalscore[1] >= config.scorelimit)) || + (config.timelimit > 0 && (server_tick()-round_start_tick) >= config.timelimit*server_tickspeed()*60)) + { + if(topscore_count == 1) + endround(); + else + sudden_death = 1; + } + } + else + { + // game over.. wait for restart + if(server_tick() > game_over_tick+server_tickspeed()*10) + startround(); + } +} diff --git a/src/game/server/srv_tdm.h b/src/game/server/srv_tdm.h new file mode 100644 index 00000000..748c2e9e --- /dev/null +++ b/src/game/server/srv_tdm.h @@ -0,0 +1,6 @@ +// game object +class gameobject_tdm : public gameobject +{ +public: + virtual void tick(); +}; |