diff options
| author | Magnus Auvinen <magnus.auvinen@gmail.com> | 2007-12-15 10:24:49 +0000 |
|---|---|---|
| committer | Magnus Auvinen <magnus.auvinen@gmail.com> | 2007-12-15 10:24:49 +0000 |
| commit | a2566b3ebd93e0bbc55a920a7be08054a9377f11 (patch) | |
| tree | 44a4612805d894168fe4b3b4c065fccc1a1686e9 /src/game/server/game_server.cpp | |
| parent | ac9873056aa1fe529b098f19ff31e9ffa0e016a2 (diff) | |
| download | zcatch-a2566b3ebd93e0bbc55a920a7be08054a9377f11.tar.gz zcatch-a2566b3ebd93e0bbc55a920a7be08054a9377f11.zip | |
cleaned up code structure a bit
Diffstat (limited to 'src/game/server/game_server.cpp')
| -rw-r--r-- | src/game/server/game_server.cpp | 1860 |
1 files changed, 0 insertions, 1860 deletions
diff --git a/src/game/server/game_server.cpp b/src/game/server/game_server.cpp deleted file mode 100644 index 658e72c9..00000000 --- a/src/game/server/game_server.cpp +++ /dev/null @@ -1,1860 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <engine/config.h> -#include "../version.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; - -class player* get_player(int index); -void create_damageind(vec2 p, float angle_mod, int amount); -void create_explosion(vec2 p, int owner, int weapon, bool bnodamage); -void create_smoke(vec2 p); -void create_spawn(vec2 p); -void create_death(vec2 p); -void create_sound(vec2 pos, int sound, int mask=-1); -class player *intersect_player(vec2 pos0, vec2 pos1, vec2 &new_pos, class entity *notthis = 0); - -game_world *world; - -////////////////////////////////////////////////// -// Event handler -////////////////////////////////////////////////// -event_handler::event_handler() -{ - clear(); -} - -void *event_handler::create(int type, int size, int mask) -{ - if(num_events == MAX_EVENTS) - return 0; - if(current_offset+size >= MAX_DATASIZE) - return 0; - - void *p = &data[current_offset]; - offsets[num_events] = current_offset; - types[num_events] = type; - sizes[num_events] = size; - client_masks[num_events] = mask; - current_offset += size; - num_events++; - return p; -} - -void event_handler::clear() -{ - num_events = 0; - current_offset = 0; -} - -void event_handler::snap(int snapping_client) -{ - for(int i = 0; i < num_events; i++) - { - if(cmask_is_set(client_masks[i], snapping_client)) - { - ev_common *ev = (ev_common *)&data[offsets[i]]; - if(distance(players[snapping_client].pos, vec2(ev->x, ev->y)) < 1500.0f) - { - void *d = snap_new_item(types[i], i, sizes[i]); - mem_copy(d, &data[offsets[i]], sizes[i]); - } - } - } -} - -event_handler events; - -////////////////////////////////////////////////// -// Entity -////////////////////////////////////////////////// -entity::entity(int objtype) -{ - this->objtype = objtype; - pos = vec2(0,0); - flags = FLAG_PHYSICS; - proximity_radius = 0; - - id = snap_new_id(); - - next_entity = 0; - prev_entity = 0; - prev_type_entity = 0; - next_type_entity = 0; -} - -entity::~entity() -{ - snap_free_id(id); -} - -////////////////////////////////////////////////// -// game world -////////////////////////////////////////////////// -game_world::game_world() -{ - paused = false; - reset_requested = false; - first_entity = 0x0; - for(int i = 0; i < NUM_ENT_TYPES; i++) - first_entity_types[i] = 0; -} - -int game_world::find_entities(vec2 pos, float radius, entity **ents, int max) -{ - int num = 0; - for(entity *ent = first_entity; ent; ent = ent->next_entity) - { - if(!(ent->flags&entity::FLAG_PHYSICS)) - continue; - - if(distance(ent->pos, pos) < radius+ent->proximity_radius) - { - ents[num] = ent; - num++; - if(num == max) - break; - } - } - - return num; -} - -int game_world::find_entities(vec2 pos, float radius, entity **ents, int max, const int* types, int maxtypes) -{ - int num = 0; - for(int t = 0; t < maxtypes; t++) - { - for(entity *ent = first_entity_types[types[t]]; ent; ent = ent->next_type_entity) - { - if(!(ent->flags&entity::FLAG_PHYSICS)) - continue; - - if(distance(ent->pos, pos) < radius+ent->proximity_radius) - { - ents[num] = ent; - num++; - if(num == max) - break; - } - } - } - - return num; -} - -void game_world::insert_entity(entity *ent) -{ - entity *cur = first_entity; - while(cur) - { - dbg_assert(cur != ent, "err"); - cur = cur->next_entity; - } - - // insert it - if(first_entity) - first_entity->prev_entity = ent; - ent->next_entity = first_entity; - ent->prev_entity = 0x0; - first_entity = ent; - - // into typelist aswell - if(first_entity_types[ent->objtype]) - first_entity_types[ent->objtype]->prev_type_entity = ent; - ent->next_type_entity = first_entity_types[ent->objtype]; - ent->prev_type_entity = 0x0; - first_entity_types[ent->objtype] = ent; -} - -void game_world::destroy_entity(entity *ent) -{ - ent->set_flag(entity::FLAG_DESTROY); -} - -void game_world::remove_entity(entity *ent) -{ - // not in the list - if(!ent->next_entity && !ent->prev_entity && first_entity != ent) - return; - - // remove - if(ent->prev_entity) - ent->prev_entity->next_entity = ent->next_entity; - else - first_entity = ent->next_entity; - if(ent->next_entity) - ent->next_entity->prev_entity = ent->prev_entity; - - if(ent->prev_type_entity) - ent->prev_type_entity->next_type_entity = ent->next_type_entity; - else - first_entity_types[ent->objtype] = ent->next_type_entity; - if(ent->next_type_entity) - ent->next_type_entity->prev_type_entity = ent->prev_type_entity; - - ent->next_entity = 0; - ent->prev_entity = 0; - ent->next_type_entity = 0; - ent->prev_type_entity = 0; -} - -// -void game_world::snap(int snapping_client) -{ - for(entity *ent = first_entity; ent; ent = ent->next_entity) - ent->snap(snapping_client); -} - -void game_world::reset() -{ - // reset all entities - for(entity *ent = first_entity; ent; ent = ent->next_entity) - ent->reset(); - remove_entities(); - - for(entity *ent = first_entity; ent; ent = ent->next_entity) - ent->post_reset(); - remove_entities(); - - reset_requested = false; -} - -void game_world::remove_entities() -{ - // destroy objects marked for destruction - entity *ent = first_entity; - while(ent) - { - entity *next = ent->next_entity; - if(ent->flags&entity::FLAG_DESTROY) - { - remove_entity(ent); - ent->destroy(); - } - ent = next; - } -} - -void game_world::tick() -{ - if(reset_requested) - reset(); - - if(!paused) - { - // update all objects - for(entity *ent = first_entity; ent; ent = ent->next_entity) - ent->tick(); - - for(entity *ent = first_entity; ent; ent = ent->next_entity) - ent->tick_defered(); - } - - remove_entities(); -} - -////////////////////////////////////////////////// -// projectile -////////////////////////////////////////////////// -projectile::projectile(int type, int owner, vec2 pos, vec2 vel, int span, entity* powner, - int damage, int flags, float force, int sound_impact, int weapon) -: entity(OBJTYPE_PROJECTILE) -{ - this->type = type; - this->pos = pos; - this->vel = vel * SERVER_TICK_SPEED; // TODO: remove this - this->lifespan = span; - this->owner = owner; - this->powner = powner; - this->flags = flags; - this->force = force; - this->damage = damage; - this->sound_impact = sound_impact; - this->weapon = weapon; - this->bounce = 0; - this->start_tick = server_tick(); - world->insert_entity(this); -} - -void projectile::reset() -{ - world->destroy_entity(this); -} - -void projectile::tick() -{ - float gravity = -400; - if(type != WEAPON_ROCKET) - gravity = -100; - - float pt = (server_tick()-start_tick-1)/(float)SERVER_TICK_SPEED; - float ct = (server_tick()-start_tick)/(float)SERVER_TICK_SPEED; - vec2 prevpos = calc_pos(pos, vel, gravity, pt); - vec2 curpos = calc_pos(pos, vel, gravity, ct); - - lifespan--; - - int collide = col_check_point((int)curpos.x, (int)curpos.y); - - vec2 new_pos; - entity *targetplayer = (entity*)intersect_player(prevpos, curpos, new_pos, powner); - - if(targetplayer || collide || lifespan < 0 ) - { - if (lifespan >= 0 || weapon == WEAPON_ROCKET) - create_sound(pos, sound_impact); - - if (flags & PROJECTILE_FLAGS_EXPLODE) - create_explosion(prevpos, owner, weapon, false); - else if (targetplayer) - { - targetplayer->take_damage(normalize(vel) * max(0.001f, force), damage, owner, weapon); - } - - world->destroy_entity(this); - } -} - -void projectile::snap(int snapping_client) -{ - float ct = (server_tick()-start_tick)/(float)SERVER_TICK_SPEED; - vec2 curpos = calc_pos(pos, vel, -7.5f*SERVER_TICK_SPEED, ct); - - if(distance(players[snapping_client].pos, curpos) > 1000.0f) - return; - - obj_projectile *proj = (obj_projectile *)snap_new_item(OBJTYPE_PROJECTILE, id, sizeof(obj_projectile)); - proj->x = (int)pos.x; - proj->y = (int)pos.y; - proj->vx = (int)vel.x; - proj->vy = (int)vel.y; - proj->start_tick = start_tick; - proj->type = type; -} - -////////////////////////////////////////////////// -// player -////////////////////////////////////////////////// -// TODO: move to separate file -player::player() -: entity(OBJTYPE_PLAYER_CHARACTER) -{ - init(); -} - -void player::init() -{ - proximity_radius = phys_size; - client_id = -1; - team = -1; // -1 == spectator - extrapowerflags = 0; - - latency_accum = 0; - latency_accum_min = 0; - latency_accum_max = 0; - latency_avg = 0; - latency_min = 0; - latency_max = 0; - - reset(); -} - -void player::reset() -{ - pos = vec2(0.0f, 0.0f); - core.vel = vec2(0.0f, 0.0f); - //direction = vec2(0.0f, 1.0f); - score = 0; - dead = true; - clear_flag(entity::FLAG_PHYSICS); - spawning = false; - die_tick = 0; - damage_taken = 0; - state = STATE_UNKNOWN; - - mem_zero(&input, sizeof(input)); - mem_zero(&previnput, sizeof(previnput)); - num_inputs = 0; - - last_action = -1; - - emote_stop = 0; - damage_taken_tick = 0; - attack_tick = 0; - numobjectshit = 0; - ninjaactivationtick = 0; - currentmovetime = 0; - - active_weapon = WEAPON_GUN; - last_weapon = WEAPON_HAMMER; - wanted_weapon = WEAPON_GUN; -} - -void player::destroy() { } - -void player::set_weapon(int w) -{ - last_weapon = active_weapon; - active_weapon = w; - if(active_weapon < 0 || active_weapon >= NUM_WEAPONS) - active_weapon = 0; -} - -void player::respawn() -{ - spawning = true; -} - - -void player::set_team(int new_team) -{ - team = new_team; - die(client_id, -1); - - dbg_msg("game", "cid=%d team=%d", client_id, team); - - if(team == -1) - clear_flag(FLAG_PHYSICS); - else - set_flag(FLAG_PHYSICS); -} - - -bool try_spawntype(int t, vec2 *outpos) -{ - // get spawn point - int start, num; - map_get_type(t, &start, &num); - if(!num) - return false; - - int id = rand()%num; - mapres_spawnpoint *sp = (mapres_spawnpoint*)map_get_item(start + id, NULL, NULL); - *outpos = vec2((float)sp->x, (float)sp->y); - return true; -} - -void player::try_respawn() -{ - vec2 spawnpos = vec2(100.0f, -60.0f); - - // get spawn point - if(gameobj->gametype == GAMETYPE_CTF) - { - // try first try own team spawn, then normal spawn and then enemy - if(!try_spawntype(MAPRES_SPAWNPOINT_RED+(team&1), &spawnpos)) - { - if(!try_spawntype(MAPRES_SPAWNPOINT, &spawnpos)) - try_spawntype(MAPRES_SPAWNPOINT_RED+((team+1)&1), &spawnpos); - } - } - else - { - if(!try_spawntype(MAPRES_SPAWNPOINT, &spawnpos)) - try_spawntype(MAPRES_SPAWNPOINT_RED+(rand()&1), &spawnpos); - } - - // check if the position is occupado - entity *ents[2] = {0}; - int types[] = {OBJTYPE_PLAYER_CHARACTER}; - int num_ents = world->find_entities(spawnpos, 64, ents, 2, types, 1); - for(int i = 0; i < num_ents; i++) - { - if(ents[i] != this) - return; - } - - spawning = false; - pos = spawnpos; - - core.pos = pos; - core.vel = vec2(0,0); - core.hooked_player = -1; - - health = 10; - armor = 0; - jumped = 0; - dead = false; - set_flag(entity::FLAG_PHYSICS); - state = STATE_PLAYING; - - core.hook_state = HOOK_IDLE; - - mem_zero(&input, sizeof(input)); - - // init weapons - mem_zero(&weapons, sizeof(weapons)); - weapons[WEAPON_HAMMER].got = true; - weapons[WEAPON_HAMMER].ammo = -1; - weapons[WEAPON_GUN].got = true; - weapons[WEAPON_GUN].ammo = data->weapons[WEAPON_GUN].maxammo; - - //weapons[WEAPON_SNIPER].got = true; - //weapons[WEAPON_SNIPER].ammo = data->weapons[WEAPON_SNIPER].maxammo; - active_weapon = WEAPON_GUN; - last_weapon = WEAPON_HAMMER; - wanted_weapon = WEAPON_GUN; - - reload_timer = 0; - - // Create sound and spawn effects - create_sound(pos, SOUND_PLAYER_SPAWN); - create_spawn(pos); - - gameobj->on_player_spawn(this); -} - -bool player::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; -} - -struct input_count -{ - int presses; - int releases; -}; - -static input_count count_input(int prev, int cur) -{ - input_count c = {0,0}; - prev &= INPUT_STATE_MASK; - cur &= INPUT_STATE_MASK; - int i = prev; - while(i != cur) - { - i = (i+1)&INPUT_STATE_MASK; - if(i&1) - c.presses++; - else - c.releases++; - } - - return c; -} - - -int player::handle_ninja() -{ - vec2 direction = normalize(vec2(input.target_x, input.target_y)); - - if ((server_tick() - ninjaactivationtick) > (data->weapons[WEAPON_NINJA].duration * server_tickspeed() / 1000)) - { - // time's up, return - weapons[WEAPON_NINJA].got = false; - active_weapon = last_weapon; - set_weapon(active_weapon); - return 0; - } - - // Check if it should activate - if (count_input(previnput.fire, input.fire).presses && (server_tick() > currentcooldown)) - { - // ok then, activate ninja - attack_tick = server_tick(); - activationdir = direction; - currentmovetime = data->weapons[WEAPON_NINJA].movetime * server_tickspeed() / 1000; - currentcooldown = data->weapons[WEAPON_NINJA].firedelay * server_tickspeed() / 1000 + server_tick(); - - // reset hit objects - numobjectshit = 0; - - create_sound(pos, SOUND_NINJA_FIRE); - - // release all hooks when ninja is activated - //release_hooked(); - //release_hooks(); - } - - currentmovetime--; - - if (currentmovetime == 0) - { - // reset player velocity - core.vel *= 0.2f; - //return MODIFIER_RETURNFLAGS_OVERRIDEWEAPON; - } - - if (currentmovetime > 0) - { - // Set player velocity - core.vel = activationdir * data->weapons[WEAPON_NINJA].velocity; - vec2 oldpos = pos; - move_box(&core.pos, &core.vel, vec2(phys_size, phys_size), 0.0f); - // reset velocity so the client doesn't predict stuff - core.vel = vec2(0.0f,0.0f); - if ((currentmovetime % 2) == 0) - { - create_smoke(pos); - } - - // check if we hit anything along the way - { - int type = OBJTYPE_PLAYER_CHARACTER; - entity *ents[64]; - vec2 dir = pos - oldpos; - float radius = phys_size * 2.0f; //length(dir * 0.5f); - vec2 center = oldpos + dir * 0.5f; - int num = world->find_entities(center, radius, ents, 64, &type, 1); - - for (int i = 0; i < num; i++) - { - // Check if entity is a player - if (ents[i] == this) - continue; - // make sure we haven't hit this object before - bool balreadyhit = false; - for (int j = 0; j < numobjectshit; j++) - { - if (hitobjects[j] == ents[i]) - balreadyhit = true; - } - if (balreadyhit) - continue; - - // check so we are sufficiently close - if (distance(ents[i]->pos, pos) > (phys_size * 2.0f)) - continue; - - // hit a player, give him damage and stuffs... - create_sound(ents[i]->pos, SOUND_NINJA_HIT); - // set his velocity to fast upward (for now) - if(numobjectshit < 10) - hitobjects[numobjectshit++] = ents[i]; - ents[i]->take_damage(vec2(0,10.0f), data->weapons[WEAPON_NINJA].meleedamage, client_id,WEAPON_NINJA); - } - } - return MODIFIER_RETURNFLAGS_OVERRIDEVELOCITY | MODIFIER_RETURNFLAGS_OVERRIDEPOSITION | MODIFIER_RETURNFLAGS_OVERRIDEGRAVITY; - } - - return 0; -} - -int player::handle_sniper() -{ - return 0; - - struct input_count button = count_input(previnput.fire, input.fire); - if (button.releases) - { - vec2 direction = normalize(vec2(input.target_x, input.target_y)); - // Check if we were charging, if so fire - if (weapons[WEAPON_SNIPER].weaponstage >= WEAPONSTAGE_SNIPER_CHARGING) - { - new projectile(projectile::WEAPON_PROJECTILETYPE_SNIPER, - client_id, pos+vec2(0,0), direction*50.0f, - 100 + weapons[WEAPON_SNIPER].weaponstage * 20,this, weapons[WEAPON_SNIPER].weaponstage, 0, 0, -1, WEAPON_SNIPER); - create_sound(pos, SOUND_SNIPER_FIRE); - } - // Add blowback - core.vel = -direction * 10.0f * weapons[WEAPON_SNIPER].weaponstage; - - // update ammo and stuff - weapons[WEAPON_SNIPER].ammo = max(0,weapons[WEAPON_SNIPER].ammo - weapons[WEAPON_SNIPER].weaponstage); - weapons[WEAPON_SNIPER].weaponstage = WEAPONSTAGE_SNIPER_NEUTRAL; - weapons[WEAPON_SNIPER].chargetick = 0; - } - else if (input.fire & 1) - { - // Charge!! (if we are on the ground) - if (is_grounded() && weapons[WEAPON_SNIPER].ammo > 0) - { - if (!weapons[WEAPON_SNIPER].chargetick) - { - weapons[WEAPON_SNIPER].chargetick = server_tick(); - dbg_msg("game", "Chargetick='%d:'", server_tick()); - } - if ((server_tick() - weapons[WEAPON_SNIPER].chargetick) > server_tickspeed() * data->weapons[active_weapon].chargetime) - { - if (weapons[WEAPON_SNIPER].ammo > weapons[WEAPON_SNIPER].weaponstage) - { - weapons[WEAPON_SNIPER].weaponstage++; - weapons[WEAPON_SNIPER].chargetick = server_tick(); - } - else if ((server_tick() - weapons[WEAPON_SNIPER].chargetick) > server_tickspeed() * data->weapons[active_weapon].overchargetime) - { - // Ooopsie, weapon exploded - create_explosion(pos, client_id, WEAPON_SNIPER, false); - create_sound(pos, SOUND_ROCKET_EXPLODE); - // remove this weapon and change weapon to gun - weapons[WEAPON_SNIPER].got = false; - weapons[WEAPON_SNIPER].ammo = 0; - last_weapon = active_weapon; - active_weapon = WEAPON_GUN; - return 0; - } - } - - // While charging, don't move - return MODIFIER_RETURNFLAGS_OVERRIDEVELOCITY|MODIFIER_RETURNFLAGS_NOHOOK; - } - else if (weapons[WEAPON_SNIPER].weaponstage) - weapons[WEAPON_SNIPER].weaponstage = WEAPONSTAGE_SNIPER_NEUTRAL; - } - return 0; -} - -int player::handle_weapons() -{ - vec2 direction = normalize(vec2(input.target_x, input.target_y)); - - if(config.dbg_stress) - { - for(int i = 0; i < NUM_WEAPONS; i++) - { - weapons[i].got = true; - weapons[i].ammo = 10; - } - - if(reload_timer) // twice as fast reload - reload_timer--; - } - - // check reload timer - if(reload_timer) - { - reload_timer--; - return 0; - } - - if (active_weapon == WEAPON_NINJA) - { - // don't update other weapons while ninja is active - return handle_ninja(); - } - - // select weapon - int next = count_input(previnput.next_weapon, input.next_weapon).presses; - int prev = count_input(previnput.prev_weapon, input.prev_weapon).presses; - - if(next < 128) // make sure we only try sane stuff - { - while(next) // next weapon selection - { - wanted_weapon = (wanted_weapon+1)%NUM_WEAPONS; - if(weapons[wanted_weapon].got) - next--; - } - } - - if(prev < 128) // make sure we only try sane stuff - { - while(prev) // prev weapon selection - { - wanted_weapon = (wanted_weapon-1)<0?NUM_WEAPONS-1:wanted_weapon-1; - if(weapons[wanted_weapon].got) - prev--; - } - } - - if(input.wanted_weapon) // direct weapon selection - wanted_weapon = input.wanted_weapon-1; - - if(wanted_weapon < 0 || wanted_weapon >= NUM_WEAPONS) - wanted_weapon = 0; - - // switch weapon if wanted - if(data->weapons[active_weapon].duration <= 0) - { - if(wanted_weapon != -1 && wanted_weapon != active_weapon && wanted_weapon >= 0 && wanted_weapon < NUM_WEAPONS && weapons[wanted_weapon].got) - { - if(active_weapon != wanted_weapon) - create_sound(pos, SOUND_WEAPON_SWITCH); - - set_weapon(wanted_weapon); - } - } - - if (active_weapon == WEAPON_SNIPER) - { - // don't update other weapons while sniper is active - return handle_sniper(); - } - - if(count_input(previnput.fire, input.fire).presses) //previnput.fire != input.fire && (input.fire&1)) - { - if(reload_timer == 0) - { - // fire! - if(weapons[active_weapon].ammo) - { - switch(active_weapon) - { - case WEAPON_HAMMER: - // reset objects hit - numobjectshit = 0; - create_sound(pos, SOUND_HAMMER_FIRE); - break; - - case WEAPON_GUN: - new projectile(WEAPON_GUN, - client_id, - pos+vec2(0,0), - direction*30.0f, - 100, - this, - 1, 0, 0, -1, WEAPON_GUN); - create_sound(pos, SOUND_GUN_FIRE); - break; - case WEAPON_ROCKET: - { - new projectile(WEAPON_ROCKET, - client_id, - pos+vec2(0,0), - direction*15.0f, - 100, - this, - 1, projectile::PROJECTILE_FLAGS_EXPLODE, 0, SOUND_ROCKET_EXPLODE, WEAPON_ROCKET); - create_sound(pos, SOUND_ROCKET_FIRE); - break; - } - case WEAPON_SHOTGUN: - { - int shotspread = 2; - for(int i = -shotspread; i <= shotspread; i++) - { - float spreading[] = {-0.12f, -0.05f, 0, 0.05f, 0.12f}; - float a = get_angle(direction); - float v = 1.0f-fabs(i/(float)shotspread); - a += spreading[i+2]; - new projectile(WEAPON_SHOTGUN, - client_id, - pos+vec2(0,0), - vec2(cosf(a), sinf(a))*(30.0f + 15.0f*v), - //vec2(cosf(a), sinf(a))*20.0f, - (int)(server_tickspeed()*0.3f), - this, - 1, 0, 0, -1, WEAPON_SHOTGUN); - } - create_sound(pos, SOUND_SHOTGUN_FIRE); - break; - } - } - - weapons[active_weapon].ammo--; - attack_tick = server_tick(); - reload_timer = data->weapons[active_weapon].firedelay * server_tickspeed() / 1000; - } - else - { - create_sound(pos, SOUND_WEAPON_NOAMMO); - } - } - } - - // Update weapons - if (active_weapon == WEAPON_HAMMER && reload_timer > 0) - { - // Handle collisions - // only one that needs update (for now) - // do selection for the weapon and bash anything in it - // check if we hit anything along the way - int type = OBJTYPE_PLAYER_CHARACTER; - entity *ents[64]; - vec2 lookdir(direction.x > 0.0f ? 1.0f : -1.0f, 0.0f); - vec2 dir = lookdir * data->weapons[active_weapon].meleereach; - float radius = length(dir * 0.5f); - vec2 center = pos + dir * 0.5f; - int num = world->find_entities(center, radius, ents, 64, &type, 1); - - for (int i = 0; i < num; i++) - { - // Check if entity is a player - if (ents[i] == this) - continue; - // make sure we haven't hit this object before - bool balreadyhit = false; - for (int j = 0; j < numobjectshit; j++) - { - if (hitobjects[j] == ents[i]) - balreadyhit = true; - } - if (balreadyhit) - continue; - - // check so we are sufficiently close - if (distance(ents[i]->pos, pos) > (phys_size * 2.0f)) - continue; - - // hit a player, give him damage and stuffs... - // create sound for bash - //create_sound(ents[i]->pos, sound_impact); - vec2 fdir = normalize(ents[i]->pos- pos); - - // set his velocity to fast upward (for now) - create_smoke(ents[i]->pos); - create_sound(pos, SOUND_HAMMER_HIT); - if(numobjectshit < 10) - hitobjects[numobjectshit++] = ents[i]; - ents[i]->take_damage(vec2(0,-1.0f), data->weapons[active_weapon].meleedamage, client_id, active_weapon); - player* target = (player*)ents[i]; - vec2 dir; - if (length(target->pos - pos) > 0.0f) - dir = normalize(target->pos - pos); - else - dir = vec2(0,-1); - - target->core.vel += normalize(dir + vec2(0,-1.1f)) * 10.0f; - } - } - - if (data->weapons[active_weapon].ammoregentime) - { - // If equipped and not active, regen ammo? - if (reload_timer <= 0) - { - if (weapons[active_weapon].ammoregenstart < 0) - weapons[active_weapon].ammoregenstart = server_tick(); - - if ((server_tick() - weapons[active_weapon].ammoregenstart) >= data->weapons[active_weapon].ammoregentime * server_tickspeed() / 1000) - { - // Add some ammo - weapons[active_weapon].ammo = min(weapons[active_weapon].ammo + 1, data->weapons[active_weapon].maxammo); - weapons[active_weapon].ammoregenstart = -1; - } - } - else - { - weapons[active_weapon].ammoregenstart = -1; - } - } - - return 0; -} - -void player::tick() -{ - // check if we have enough input - // this is to prevent initial weird clicks - if(num_inputs < 2) - previnput = input; - - // do latency stuff - { - CLIENT_INFO info; - if(server_getclientinfo(client_id, &info)) - { - latency_accum += info.latency; - latency_accum_max = max(latency_accum_max, info.latency); - latency_accum_min = min(latency_accum_min, info.latency); - } - - if(server_tick()%server_tickspeed() == 0) - { - latency_avg = latency_accum/server_tickspeed(); - latency_max = latency_accum_max; - latency_min = latency_accum_min; - latency_accum = 0; - latency_accum_min = 1000; - latency_accum_max = 0; - } - } - - // enable / disable physics - if(team == -1 || dead) - world->core.players[client_id] = 0; - else - world->core.players[client_id] = &core; - - // spectator - if(team == -1) - return; - - if(spawning) - try_respawn(); - - // TODO: rework the input to be more robust - if(dead) - { - if(server_tick()-die_tick >= server_tickspeed()*5) // auto respawn after 3 sec - respawn(); - if((input.fire&1) && server_tick()-die_tick >= server_tickspeed()/2) // auto respawn after 0.5 sec - respawn(); - return; - } - - //player_core core; - //core.pos = pos; - //core.jumped = jumped; - core.input = input; - core.tick(); - - // handle weapons - handle_weapons(); - - state = input.state; - - // Previnput - previnput = input; - return; -} - -void player::tick_defered() -{ - if(!dead) - { - vec2 start_pos = core.pos; - vec2 start_vel = core.vel; - bool stuck_before = test_box(core.pos, vec2(28.0f, 28.0f)); - core.move(); - bool stuck_after_move = test_box(core.pos, vec2(28.0f, 28.0f)); - core.quantize(); - bool stuck_after_quant = test_box(core.pos, vec2(28.0f, 28.0f)); - pos = core.pos; - - if(!stuck_before && (stuck_after_move || stuck_after_quant)) - { - dbg_msg("player", "STUCK!!! %d %d %d %f %f %f %f %x %x %x %x", - stuck_before, - stuck_after_move, - stuck_after_quant, - start_pos.x, start_pos.y, - start_vel.x, start_vel.y, - *((unsigned *)&start_pos.x), *((unsigned *)&start_pos.y), - *((unsigned *)&start_vel.x), *((unsigned *)&start_vel.y)); - } - - - int events = core.triggered_events; - int mask = cmask_all_except_one(client_id); - - if(events&COREEVENT_GROUND_JUMP) create_sound(pos, SOUND_PLAYER_JUMP, mask); - if(events&COREEVENT_AIR_JUMP) - { - create_sound(pos, SOUND_PLAYER_JUMP, mask); - ev_common *c = (ev_common *)::events.create(EVENT_AIR_JUMP, sizeof(ev_common), mask); - if(c) - { - c->x = (int)pos.x; - c->y = (int)pos.y; - } - } - - //if(events&COREEVENT_HOOK_LAUNCH) snd_play_random(CHN_WORLD, SOUND_HOOK_LOOP, 1.0f, pos); - if(events&COREEVENT_HOOK_ATTACH_PLAYER) create_sound(pos, SOUND_HOOK_ATTACH_PLAYER, mask); - if(events&COREEVENT_HOOK_ATTACH_GROUND) create_sound(pos, SOUND_HOOK_ATTACH_GROUND, mask); - //if(events&COREEVENT_HOOK_RETRACT) snd_play_random(CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos); - - } - - if(team == -1) - { - pos.x = input.target_x; - pos.y = input.target_y; - } -} - -void player::die(int killer, int weapon) -{ - int mode_special = gameobj->on_player_death(this, get_player(killer), weapon); - - dbg_msg("game", "kill killer='%d:%s' victim='%d:%s' weapon=%d special=%d", - killer, server_clientname(killer), - client_id, server_clientname(client_id), weapon, mode_special); - - // send the kill message - msg_pack_start(MSG_KILLMSG, MSGFLAG_VITAL); - msg_pack_int(killer); - msg_pack_int(client_id); - msg_pack_int(weapon); - msg_pack_int(mode_special); - msg_pack_end(); - server_send_msg(-1); - - // a nice sound - create_sound(pos, SOUND_PLAYER_DIE); - - // set dead state - dead = true; - die_tick = server_tick(); - clear_flag(FLAG_PHYSICS); - create_death(pos); -} - -bool player::take_damage(vec2 force, int dmg, int from, int weapon) -{ - core.vel += force; - - if(gameobj->is_friendly_fire(client_id, from) && !config.sv_teamdamage) - return false; - - // player only inflicts half damage on self - if(from == client_id) - dmg = max(1, dmg/2); - - // CTF and TDM (TODO: check for FF) - //if (gameobj->gametype != GAMETYPE_DM && from >= 0 && players[from].team == team) - //return false; - - damage_taken++; - - // create healthmod indicator - if(server_tick() < damage_taken_tick+25) - { - // make sure that the damage indicators doesn't group together - create_damageind(pos, damage_taken*0.25f, dmg); - } - else - { - damage_taken = 0; - create_damageind(pos, 0, dmg); - } - - if(armor) - { - armor -= 1; - dmg--; - } - - if(dmg > armor) - { - dmg -= armor; - armor = 0; - health -= dmg; - } - else - armor -= dmg; - - damage_taken_tick = server_tick(); - - // do damage hit sound - if(from >= 0) - create_sound(get_player(from)->pos, SOUND_HIT, cmask_one(from)); - - // check for death - if(health <= 0) - { - die(from, weapon); - - // set attacker's face to happy (taunt!) - if (from >= 0 && from != client_id) - { - player *p = get_player(from); - - p->emote_type = EMOTE_HAPPY; - p->emote_stop = server_tick() + server_tickspeed(); - } - - return false; - } - - if (dmg > 2) - create_sound(pos, SOUND_PLAYER_PAIN_LONG); - else - create_sound(pos, SOUND_PLAYER_PAIN_SHORT); - - emote_type = EMOTE_PAIN; - emote_stop = server_tick() + 500 * server_tickspeed() / 1000; - - // spawn blood? - return true; -} - -void player::snap(int snaping_client) -{ - if(1) - { - obj_player_info *info = (obj_player_info *)snap_new_item(OBJTYPE_PLAYER_INFO, client_id, sizeof(obj_player_info)); - - info->latency = latency_avg; - info->latency_flux = latency_max-latency_min; - info->local = 0; - info->clientid = client_id; - info->score = score; - info->team = team; - - if(client_id == snaping_client) - info->local = 1; - } - - if(health > 0 && distance(players[snaping_client].pos, pos) < 1000.0f) - { - obj_player_character *character = (obj_player_character *)snap_new_item(OBJTYPE_PLAYER_CHARACTER, client_id, sizeof(obj_player_character)); - - core.write(character); - - // this is to make sure that players that are just standing still - // isn't sent. this is because the physics keep bouncing between - // 0-128 when just standing. - // TODO: fix the physics so this isn't needed - if(snaping_client != client_id && abs(character->vy) < 256.0f) - character->vy = 0; - - if (emote_stop < server_tick()) - { - emote_type = EMOTE_NORMAL; - emote_stop = -1; - } - - character->emote = emote_type; - - character->ammocount = weapons[active_weapon].ammo; - character->health = 0; - character->armor = 0; - character->weapon = active_weapon; - character->weaponstage = weapons[active_weapon].weaponstage; - character->attacktick = attack_tick; - - if(client_id == snaping_client) - { - character->health = health; - character->armor = armor; - } - - if(dead) - character->health = -1; - - //if(length(vel) > 15.0f) - // player->emote = EMOTE_HAPPY; - - //if(damage_taken_tick+50 > server_tick()) - // player->emote = EMOTE_PAIN; - - if (character->emote == EMOTE_NORMAL) - { - if(250 - ((server_tick() - last_action)%(250)) < 5) - character->emote = EMOTE_BLINK; - } - - character->state = state; - } -} - -player *players; - -////////////////////////////////////////////////// -// powerup -////////////////////////////////////////////////// -powerup::powerup(int _type, int _subtype) -: entity(OBJTYPE_POWERUP) -{ - type = _type; - subtype = _subtype; - proximity_radius = phys_size; - - reset(); - - // TODO: should this be done here? - world->insert_entity(this); -} - -void powerup::reset() -{ - if (data->powerupinfo[type].startspawntime > 0) - spawntick = server_tick() + server_tickspeed() * data->powerupinfo[type].startspawntime; - else - spawntick = -1; -} - - -void send_weapon_pickup(int cid, int weapon); - -void powerup::tick() -{ - // wait for respawn - if(spawntick > 0) - { - if(server_tick() > spawntick) - { - // respawn - spawntick = -1; - - if(type == POWERUP_WEAPON) - create_sound(pos, SOUND_WEAPON_SPAWN); - } - else - return; - } - // Check if a player intersected us - vec2 meh; - player* pplayer = intersect_player(pos, pos + vec2(0,16), meh, 0); - if (pplayer) - { - // player picked us up, is someone was hooking us, let them go - int respawntime = -1; - switch (type) - { - case POWERUP_HEALTH: - if(pplayer->health < 10) - { - create_sound(pos, SOUND_PICKUP_HEALTH); - pplayer->health = min(10, pplayer->health + data->powerupinfo[type].amount); - respawntime = data->powerupinfo[type].respawntime; - } - break; - case POWERUP_ARMOR: - if(pplayer->armor < 10) - { - create_sound(pos, SOUND_PICKUP_ARMOR); - pplayer->armor = min(10, pplayer->armor + data->powerupinfo[type].amount); - respawntime = data->powerupinfo[type].respawntime; - } - break; - - case POWERUP_WEAPON: - if(subtype >= 0 && subtype < NUM_WEAPONS) - { - if(pplayer->weapons[subtype].ammo < 10 || !pplayer->weapons[subtype].got) - { - pplayer->weapons[subtype].got = true; - pplayer->weapons[subtype].ammo = min(10, pplayer->weapons[subtype].ammo + data->powerupinfo[type].amount); - respawntime = data->powerupinfo[type].respawntime; - - // TODO: data compiler should take care of stuff like this - if(subtype == WEAPON_ROCKET) - create_sound(pos, SOUND_PICKUP_ROCKET); - else if(subtype == WEAPON_SHOTGUN) - create_sound(pos, SOUND_PICKUP_SHOTGUN); - - send_weapon_pickup(pplayer->client_id, subtype); - } - } - break; - case POWERUP_NINJA: - { - // activate ninja on target player - pplayer->ninjaactivationtick = server_tick(); - pplayer->weapons[WEAPON_NINJA].got = true; - pplayer->last_weapon = pplayer->active_weapon; - pplayer->active_weapon = WEAPON_NINJA; - respawntime = data->powerupinfo[type].respawntime; - create_sound(pos, SOUND_PICKUP_NINJA); - - // loop through all players, setting their emotes - entity *ents[64]; - const int types[] = {OBJTYPE_PLAYER_CHARACTER}; - int num = world->find_entities(vec2(0, 0), 1000000, ents, 64, types, 1); - for (int i = 0; i < num; i++) - { - player *p = (player *)ents[i]; - if (p != pplayer) - { - p->emote_type = EMOTE_SURPRISE; - p->emote_stop = server_tick() + server_tickspeed(); - } - } - - pplayer->emote_type = EMOTE_ANGRY; - pplayer->emote_stop = server_tick() + 1200 * server_tickspeed() / 1000; - - break; - } - default: - break; - }; - - if(respawntime >= 0) - { - dbg_msg("game", "pickup player='%d:%s' item=%d/%d", - pplayer->client_id, server_clientname(pplayer->client_id), type, subtype); - spawntick = server_tick() + server_tickspeed() * respawntime; - } - } -} - -void powerup::snap(int snapping_client) -{ - if(spawntick != -1) - return; - - obj_powerup *up = (obj_powerup *)snap_new_item(OBJTYPE_POWERUP, id, sizeof(obj_powerup)); - up->x = (int)pos.x; - up->y = (int)pos.y; - up->type = type; // TODO: two diffrent types? what gives? - up->subtype = subtype; -} - -// POWERUP END /////////////////////// - -player *get_player(int index) -{ - return &players[index]; -} - -void create_damageind(vec2 p, float angle, int amount) -{ - float a = 3 * 3.14159f / 2 + angle; - //float a = get_angle(dir); - float s = a-pi/3; - float e = a+pi/3; - for(int i = 0; i < amount; i++) - { - float f = mix(s, e, float(i+1)/float(amount+2)); - ev_damageind *ev = (ev_damageind *)events.create(EVENT_DAMAGEINDICATION, sizeof(ev_damageind)); - if(ev) - { - ev->x = (int)p.x; - ev->y = (int)p.y; - ev->angle = (int)(f*256.0f); - } - } -} - -void create_explosion(vec2 p, int owner, int weapon, bool bnodamage) -{ - // create the event - ev_explosion *ev = (ev_explosion *)events.create(EVENT_EXPLOSION, sizeof(ev_explosion)); - if(ev) - { - ev->x = (int)p.x; - ev->y = (int)p.y; - } - - if (!bnodamage) - { - // deal damage - entity *ents[64]; - const float radius = 128.0f; - const float innerradius = 42.0f; - int num = world->find_entities(p, radius, ents, 64); - for(int i = 0; i < num; i++) - { - vec2 diff = ents[i]->pos - p; - vec2 forcedir(0,1); - float l = length(diff); - if(l) - forcedir = normalize(diff); - l = 1-clamp((l-innerradius)/(radius-innerradius), 0.0f, 1.0f); - float dmg = 6 * l; - if((int)dmg) - ents[i]->take_damage(forcedir*dmg*2, (int)dmg, owner, weapon); - } - } -} - -void create_smoke(vec2 p) -{ - // create the event - ev_explosion *ev = (ev_explosion *)events.create(EVENT_SMOKE, sizeof(ev_explosion)); - if(ev) - { - ev->x = (int)p.x; - ev->y = (int)p.y; - } -} - -void create_spawn(vec2 p) -{ - // create the event - ev_spawn *ev = (ev_spawn *)events.create(EVENT_SPAWN, sizeof(ev_spawn)); - if(ev) - { - ev->x = (int)p.x; - ev->y = (int)p.y; - } -} - -void create_death(vec2 p) -{ - // create the event - ev_death *ev = (ev_death *)events.create(EVENT_DEATH, sizeof(ev_death)); - if(ev) - { - ev->x = (int)p.x; - ev->y = (int)p.y; - } -} - -void create_sound(vec2 pos, int sound, int mask) -{ - if (sound < 0) - return; - - // create a sound - ev_sound *ev = (ev_sound *)events.create(EVENT_SOUND_WORLD, sizeof(ev_sound), mask); - if(ev) - { - ev->x = (int)pos.x; - ev->y = (int)pos.y; - ev->sound = sound; - } -} - -void create_sound_global(int sound, int target) -{ - if (sound < 0) - return; - - msg_pack_start(MSG_SOUND_GLOBAL, MSGFLAG_VITAL); - msg_pack_int(sound); - server_send_msg(-1); -} - -// TODO: should be more general -player* intersect_player(vec2 pos0, vec2 pos1, vec2& new_pos, entity* notthis) -{ - // Find other players - entity *ents[64]; - vec2 dir = pos1 - pos0; - float radius = length(dir * 0.5f); - vec2 center = pos0 + dir * 0.5f; - const int types[] = {OBJTYPE_PLAYER_CHARACTER}; - int num = world->find_entities(center, radius, ents, 64, types, 1); - for (int i = 0; i < num; i++) - { - // Check if entity is a player - if (ents[i] != notthis) - { - new_pos = ents[i]->pos; - return (player*)ents[i]; - } - } - - return 0; -} - - -void send_chat(int cid, int team, const char *msg) -{ - if(cid >= 0 && cid < MAX_CLIENTS) - dbg_msg("chat", "%d:%d:%s: %s", cid, team, server_clientname(cid), msg); - else - dbg_msg("chat", "*** %s", msg); - - if(team == -1) - { - msg_pack_start(MSG_CHAT, MSGFLAG_VITAL); - msg_pack_int(cid); - msg_pack_int(0); - msg_pack_string(msg, 512); - msg_pack_end(); - server_send_msg(-1); - } - else - { - msg_pack_start(MSG_CHAT, MSGFLAG_VITAL); - msg_pack_int(cid); - msg_pack_int(1); - msg_pack_string(msg, 512); - msg_pack_end(); - - for(int i = 0; i < MAX_CLIENTS; i++) - { - if(players[i].client_id != -1 && players[i].team == team) - server_send_msg(i); - } - } -} - - -// Server hooks -void mods_tick() -{ - // clear all events - events.clear(); - world->tick(); - - if(world->paused) // make sure that the game object always updates - gameobj->tick(); - - if(config.sv_restart) - { - if(config.sv_restart > 1) - gameobj->do_warmup(config.sv_restart); - else - gameobj->startround(); - - config.sv_restart = 0; - } - - if(config.sv_msg[0] != 0) - { - send_chat(-1, 0, config.sv_msg); - config.sv_msg[0] = 0; - } -} - -void mods_snap(int client_id) -{ - world->snap(client_id); - events.snap(client_id); -} - -void mods_client_input(int client_id, void *input) -{ - if(!world->paused) - { - if (memcmp(&players[client_id].input, input, sizeof(player_input)) != 0) - players[client_id].last_action = server_tick(); - - //players[client_id].previnput = players[client_id].input; - players[client_id].input = *(player_input*)input; - players[client_id].num_inputs++; - } -} - -void send_info(int who, int to_who) -{ - msg_pack_start(MSG_SETINFO, MSGFLAG_VITAL); - msg_pack_int(who); - msg_pack_string(server_clientname(who), 64); - msg_pack_string(players[who].skin_name, 64); - msg_pack_int(players[who].use_custom_color); - msg_pack_int(players[who].color_body); - msg_pack_int(players[who].color_feet); - msg_pack_end(); - server_send_msg(to_who); -} - -void send_emoticon(int cid, int emoticon) -{ - msg_pack_start(MSG_EMOTICON, MSGFLAG_VITAL); - msg_pack_int(cid); - msg_pack_int(emoticon % 16); - msg_pack_end(); - server_send_msg(-1); -} - -void send_weapon_pickup(int cid, int weapon) -{ - msg_pack_start(MSG_WEAPON_PICKUP, MSGFLAG_VITAL); - msg_pack_int(weapon); - msg_pack_end(); - server_send_msg(cid); -} - -void mods_client_enter(int client_id) -{ - world->insert_entity(&players[client_id]); - players[client_id].respawn(); - dbg_msg("game", "join player='%d:%s'", client_id, server_clientname(client_id)); - - char buf[512]; - sprintf(buf, "%s has joined the game", server_clientname(client_id)); - send_chat(-1, -1, buf); -} - -void mods_connected(int client_id) -{ - players[client_id].init(); - players[client_id].client_id = client_id; - - //dbg_msg("game", "connected player='%d:%s'", client_id, server_clientname(client_id)); - - // Check which team the player should be on - if(gameobj->gametype == GAMETYPE_DM) - players[client_id].team = 0; - else - players[client_id].team = gameobj->getteam(client_id); -} - -void mods_client_drop(int client_id) -{ - char buf[512]; - sprintf(buf, "%s has left the game", server_clientname(client_id)); - send_chat(-1, -1, buf); - - dbg_msg("game", "leave player='%d:%s'", client_id, server_clientname(client_id)); - - gameobj->on_player_death(&players[client_id], 0, -1); - world->remove_entity(&players[client_id]); - world->core.players[client_id] = 0x0; - players[client_id].client_id = -1; -} - -void mods_message(int msg, int client_id) -{ - if(msg == MSG_SAY) - { - int team = msg_unpack_int(); - const char *text = msg_unpack_string(); - if(team) - team = players[client_id].team; - else - team = -1; - send_chat(client_id, team, text); - } - else if (msg == MSG_SETTEAM) - { - // Switch team on given client and kill/respawn him - players[client_id].set_team(msg_unpack_int()); - gameobj->on_player_info_change(&players[client_id]); - - // send all info to this client - for(int i = 0; i < MAX_CLIENTS; i++) - { - if(players[i].client_id != -1) - send_info(i, -1); - } - } - else if (msg == MSG_CHANGEINFO || msg == MSG_STARTINFO) - { - const char *name = msg_unpack_string(); - const char *skin_name = msg_unpack_string(); - players[client_id].use_custom_color = msg_unpack_int(); - players[client_id].color_body = msg_unpack_int(); - players[client_id].color_feet = msg_unpack_int(); - - // check for invalid chars - const char *p = name; - while (*p) - { - if(*p < 32) - return; - p++; - } - - // - if(msg == MSG_CHANGEINFO && strcmp(name, server_clientname(client_id)) != 0) - { - char msg[256]; - sprintf(msg, "*** %s changed name to %s", server_clientname(client_id), name); - send_chat(-1, -1, msg); - } - - //send_set_name(client_id, players[client_id].name, name); - strncpy(players[client_id].skin_name, skin_name, 64); - server_setclientname(client_id, name); - - gameobj->on_player_info_change(&players[client_id]); - - if(msg == MSG_STARTINFO) - { - // send all info to this client - for(int i = 0; i < MAX_CLIENTS; i++) - { - if(players[i].client_id != -1) - send_info(i, client_id); - } - - msg_pack_start(MSG_READY_TO_ENTER, MSGFLAG_VITAL); - msg_pack_end(); - server_send_msg(client_id); - } - - send_info(client_id, -1); - } - else if (msg == MSG_EMOTICON) - { - int emoteicon = msg_unpack_int(); - send_emoticon(client_id, emoteicon % 16); - } -} - -extern unsigned char internal_data[]; - -void mods_init() -{ - if(!data) /* only load once */ - data = load_data_from_memory(internal_data); - - col_init(32); - - world = new game_world; - players = new player[MAX_CLIENTS]; - - // select gametype - if(strcmp(config.sv_gametype, "ctf") == 0) - gameobj = new gameobject_ctf; - else if(strcmp(config.sv_gametype, "tdm") == 0) - gameobj = new gameobject_tdm; - else - gameobj = new gameobject_dm; - - // setup core world - for(int i = 0; i < MAX_CLIENTS; i++) - players[i].core.world = &world->core; - - // - int start, num; - map_get_type(MAPRES_ITEM, &start, &num); - - // TODO: this is way more complicated then it should be - for(int i = 0; i < num; i++) - { - mapres_item *it = (mapres_item *)map_get_item(start+i, 0, 0); - - int type = -1; - int subtype = 0; - - switch(it->type) - { - case ITEM_WEAPON_GUN: - type = POWERUP_WEAPON; - subtype = WEAPON_GUN; - break; - case ITEM_WEAPON_SHOTGUN: - type = POWERUP_WEAPON; - subtype = WEAPON_SHOTGUN; - break; - case ITEM_WEAPON_ROCKET: - type = POWERUP_WEAPON; - subtype = WEAPON_ROCKET; - break; - case ITEM_WEAPON_HAMMER: - type = POWERUP_WEAPON; - subtype = WEAPON_HAMMER; - break; - - case ITEM_HEALTH: - type = POWERUP_HEALTH; - break; - - case ITEM_ARMOR: - type = POWERUP_ARMOR; - break; - - case ITEM_NINJA: - if(config.sv_powerups) - { - type = POWERUP_NINJA; - subtype = WEAPON_NINJA; - } - break; - }; - - if(type != -1) - { - // LOL, the only new in the entire game code - // perhaps we can get rid of it. seems like a stupid thing to have - powerup *ppower = new powerup(type, subtype); - ppower->pos = vec2(it->x, it->y); - } - } - - if(gameobj->gametype == GAMETYPE_CTF) - { - } - - world->insert_entity(gameobj); - - - if(config.dbg_bots) - { - - for(int i = 0; i < config.dbg_bots ; i++) - { - mods_connected(MAX_CLIENTS-i-1); - mods_client_enter(MAX_CLIENTS-i-1); - if(gameobj->gametype != GAMETYPE_DM) - players[MAX_CLIENTS-i-1].team = i&1; - } - } -} - -void mods_shutdown() -{ - delete [] players; - delete gameobj; - delete world; - gameobj = 0; - players = 0; - world = 0; -} - -void mods_presnap() {} -void mods_postsnap() {} - -extern "C" const char *mods_net_version() { return TEEWARS_NETVERSION; } |