diff options
Diffstat (limited to 'src/game')
| -rw-r--r-- | src/game/client/game_client.cpp | 169 | ||||
| -rw-r--r-- | src/game/game.h | 74 | ||||
| -rw-r--r-- | src/game/game_protocol.h | 37 | ||||
| -rw-r--r-- | src/game/game_variables.h | 3 | ||||
| -rw-r--r-- | src/game/server/game_server.cpp | 437 | ||||
| -rw-r--r-- | src/game/server/game_server.h | 29 |
6 files changed, 314 insertions, 435 deletions
diff --git a/src/game/client/game_client.cpp b/src/game/client/game_client.cpp index 87fe767c..cc91c923 100644 --- a/src/game/client/game_client.cpp +++ b/src/game/client/game_client.cpp @@ -39,6 +39,7 @@ struct client_data int team; int emoticon; int emoticon_start; + player_core predicted; } client_datas[MAX_CLIENTS]; inline float frandom() { return rand()/(float)(RAND_MAX); } @@ -137,6 +138,7 @@ void draw_sprite(float x, float y, float size) gfx_quads_draw(x, y, size*sprite_w_scale, size*sprite_h_scale); } +/* void move_point(vec2 *inout_pos, vec2 *inout_vel, float elasticity) { vec2 pos = *inout_pos; @@ -166,7 +168,7 @@ void move_point(vec2 *inout_pos, vec2 *inout_vel, float elasticity) { *inout_pos = pos + vel; } -} +}*/ class damage_indicators { @@ -309,7 +311,7 @@ public: particles[i].vel.y += particles[i].gravity*time_passed; particles[i].vel *= particles[i].friction; vec2 vel = particles[i].vel*time_passed; - move_point(&particles[i].pos, &vel, 0.1f+0.9f*frandom()); + move_point(&particles[i].pos, &vel, 0.1f+0.9f*frandom(), NULL); particles[i].vel = vel* (1.0f/time_passed); particles[i].life += time_passed; particles[i].rot += time_passed * particles[i].rotspeed; @@ -681,6 +683,75 @@ static void process_events(int s) must_process_events = false; } +static player_core predicted_prev_player; +static player_core predicted_player; + +extern "C" void modc_predict() +{ + // repredict player + { + world_core world; + int local_cid = -1; + + // search for players + for(int i = 0; i < snap_num_items(SNAP_CURRENT); i++) + { + SNAP_ITEM item; + const void *data = snap_get_item(SNAP_CURRENT, i, &item); + + if(item.type == OBJTYPE_PLAYER) + { + const obj_player *player = (const obj_player *)data; + client_datas[player->clientid].predicted.world = &world; + world.players[player->clientid] = &client_datas[player->clientid].predicted; + + client_datas[player->clientid].predicted.read(player); + if(player->local) + local_cid = player->clientid; + } + } + + // predict + for(int tick = client_tick(); tick <= client_predtick(); tick++) + { + // first calculate where everyone should move + for(int c = 0; c < MAX_CLIENTS; c++) + { + if(!world.players[c]) + continue; + + mem_zero(&world.players[c]->input, sizeof(world.players[c]->input)); + if(local_cid == c) + { + // apply player input + int *input = client_get_input(tick); + if(input) + world.players[c]->input = *((player_input*)input); + } + + world.players[c]->tick(); + } + + // move all players and quantize their data + for(int c = 0; c < MAX_CLIENTS; c++) + { + if(!world.players[c]) + continue; + + world.players[c]->move(); + world.players[c]->quantize(); + } + } + + // get the data from the local player + if(local_cid != -1) + { + predicted_prev_player = predicted_player; + predicted_player = *world.players[local_cid]; + } + } +} + extern "C" void modc_newsnapshot() { if(must_process_events) @@ -945,7 +1016,7 @@ static void render_tee(animstate *anim, int skin, int emote, vec2 dir, vec2 pos) // first pass we draw the outline // second pass we draw the filling int outline = p==0 ? 1 : 0; - int shift = charids[skin%16]; + int shift = skin; for(int f = 0; f < 2; f++) { @@ -1070,22 +1141,37 @@ void draw_round_rect(float x, float y, float w, float h, float r) gfx_quads_drawTL(x+w-r, y+r, r, h-r*2); // right } -static void render_player(const obj_player *prev, const obj_player *player) +static void render_player(const obj_player *prev_obj, const obj_player *player_obj) { - if(player->health < 0) // dont render dead players + obj_player prev; + obj_player player; + prev = *prev_obj; + player = *player_obj; + + if(player.health < 0) // dont render dead players return; + + if(player.local) + { + // apply predicted results + predicted_player.write(&player); + predicted_prev_player.write(&prev); + } - int skin = gametype == GAMETYPE_DM ? player->clientid : skinseed + player->team; + int skin = charids[player.clientid]; + + if(gametype != GAMETYPE_DM) + skin = player.team*9; // 0 or 9 - vec2 direction = get_direction(player->angle); - float angle = player->angle/256.0f; - vec2 position = mix(vec2(prev->x, prev->y), vec2(player->x, player->y), client_intratick()); + vec2 direction = get_direction(player.angle); + float angle = player.angle/256.0f; + vec2 position = mix(vec2(prev.x, prev.y), vec2(player.x, player.y), client_intratick()); - if(prev->health < 0) // Don't flicker from previous position - position = vec2(player->x, player->y); + if(prev.health < 0) // Don't flicker from previous position + position = vec2(player.x, player.y); - bool stationary = player->vx < 1 && player->vx > -1; - bool inair = col_check_point(player->x, player->y+16) == 0; + bool stationary = player.vx < 1 && player.vx > -1; + bool inair = col_check_point(player.x, player.y+16) == 0; // evaluate animation float walk_time = fmod(position.x, 100.0f)/100.0f; @@ -1099,26 +1185,26 @@ static void render_player(const obj_player *prev, const obj_player *player) else anim_eval_add(&state, &data->animations[ANIM_WALK], walk_time, 1.0f); - if (player->weapon == WEAPON_HAMMER) + if (player.weapon == WEAPON_HAMMER) { - float a = clamp((client_tick()-player->attacktick+client_intratick())/10.0f, 0.0f, 1.0f); + float a = clamp((client_tick()-player.attacktick+client_intratick())/10.0f, 0.0f, 1.0f); anim_eval_add(&state, &data->animations[ANIM_HAMMER_SWING], a, 1.0f); } - if (player->weapon == WEAPON_NINJA) + if (player.weapon == WEAPON_NINJA) { - float a = clamp((client_tick()-player->attacktick+client_intratick())/40.0f, 0.0f, 1.0f); + float a = clamp((client_tick()-player.attacktick+client_intratick())/40.0f, 0.0f, 1.0f); anim_eval_add(&state, &data->animations[ANIM_NINJA_SWING], a, 1.0f); } // draw hook - if (prev->hook_active && player->hook_active) + if (prev.hook_state>0 && player.hook_state>0) { gfx_texture_set(data->images[IMAGE_GAME].id); gfx_quads_begin(); //gfx_quads_begin(); vec2 pos = position; - vec2 hook_pos = mix(vec2(prev->hook_x, prev->hook_y), vec2(player->hook_x, player->hook_y), client_intratick()); + vec2 hook_pos = mix(vec2(prev.hook_x, prev.hook_y), vec2(player.hook_x, player.hook_y), client_intratick()); float d = distance(pos, hook_pos); vec2 dir = normalize(pos-hook_pos); @@ -1150,13 +1236,13 @@ static void render_player(const obj_player *prev, const obj_player *player) gfx_quads_setrotation(state.attach.angle*pi*2+angle); // normal weapons - int iw = clamp(player->weapon, 0, NUM_WEAPONS-1); + int iw = clamp(player.weapon, 0, NUM_WEAPONS-1); select_sprite(data->weapons[iw].sprite_body, direction.x < 0 ? SPRITE_FLAG_FLIP_Y : 0); vec2 dir = direction; float recoil = 0.0f; vec2 p; - if (player->weapon == WEAPON_HAMMER) + if (player.weapon == WEAPON_HAMMER) { // Static position for hammer p = position; @@ -1173,7 +1259,7 @@ static void render_player(const obj_player *prev, const obj_player *player) } draw_sprite(p.x, p.y, data->weapons[iw].visual_size); } - else if (player->weapon == WEAPON_NINJA) + else if (player.weapon == WEAPON_NINJA) { p = position; p.y += data->weapons[iw].offsety; @@ -1190,13 +1276,13 @@ static void render_player(const obj_player *prev, const obj_player *player) draw_sprite(p.x, p.y, data->weapons[iw].visual_size); // HADOKEN - if ((client_tick()-player->attacktick) <= (SERVER_TICK_SPEED / 6) && data->weapons[iw].nummuzzlesprites) + if ((client_tick()-player.attacktick) <= (SERVER_TICK_SPEED / 6) && data->weapons[iw].nummuzzlesprites) { int itex = rand() % data->weapons[iw].nummuzzlesprites; float alpha = 1.0f; if (alpha > 0.0f && data->weapons[iw].sprite_muzzle[itex].psprite) { - vec2 dir = vec2(player->x,player->y) - vec2(prev->x, prev->y); + vec2 dir = vec2(player.x,player.y) - vec2(prev.x, prev.y); dir = normalize(dir); float hadokenangle = atan(dir.y/dir.x); if (dir.x < 0.0f) @@ -1216,7 +1302,7 @@ static void render_player(const obj_player *prev, const obj_player *player) { // TODO: should be an animation recoil = 0; - float a = (client_tick()-player->attacktick+client_intratick())/5.0f; + float a = (client_tick()-player.attacktick+client_intratick())/5.0f; if(a < 1) recoil = sinf(a*pi); p = position + dir * data->weapons[iw].offsetx - dir*recoil*10.0f; @@ -1224,13 +1310,13 @@ static void render_player(const obj_player *prev, const obj_player *player) draw_sprite(p.x, p.y, data->weapons[iw].visual_size); } - if (player->weapon == WEAPON_GUN || player->weapon == WEAPON_SHOTGUN) + if (player.weapon == WEAPON_GUN || player.weapon == WEAPON_SHOTGUN) { // check if we're firing stuff - if (true)///prev->attackticks) + if (true)///prev.attackticks) { float alpha = 0.0f; - int phase1tick = (client_tick() - player->attacktick); + int phase1tick = (client_tick() - player.attacktick); if (phase1tick < (data->weapons[iw].muzzleduration + 3)) { float intratick = client_intratick(); @@ -1252,14 +1338,14 @@ static void render_player(const obj_player *prev, const obj_player *player) draw_sprite(p.x, p.y, data->weapons[iw].visual_size); /*gfx_quads_setcolor(1.0f,1.0f,1.0f,alpha); vec2 diry(-dir.y,dir.x); - p += dir * muzzleparams[player->weapon].offsetx + diry * offsety; - gfx_quads_draw(p.x,p.y,muzzleparams[player->weapon].sizex, muzzleparams[player->weapon].sizey);*/ + p += dir * muzzleparams[player.weapon].offsetx + diry * offsety; + gfx_quads_draw(p.x,p.y,muzzleparams[player.weapon].sizex, muzzleparams[player.weapon].sizey);*/ } } } gfx_quads_end(); - switch (player->weapon) + switch (player.weapon) { case WEAPON_GUN: render_hand(skin, p, direction, -3*pi/4, vec2(-15, 4)); break; case WEAPON_SHOTGUN: render_hand(skin, p, direction, -pi/2, vec2(-5, 4)); break; @@ -1269,9 +1355,15 @@ static void render_player(const obj_player *prev, const obj_player *player) } // render the tee - render_tee(&state, skin, player->emote, direction, position); + if(player.local && config.debug) + { + vec2 ghost_position = mix(vec2(prev_obj->x, prev_obj->y), vec2(player_obj->x, player_obj->y), client_intratick()); + render_tee(&state, 15, player.emote, direction, ghost_position); // render ghost + } + + render_tee(&state, skin, player.emote, direction, position); - if(player->state == STATE_CHATTING) + if(player.state == STATE_CHATTING) { gfx_texture_set(data->images[IMAGE_CHAT_BUBBLES].id); gfx_quads_begin(); @@ -1280,13 +1372,13 @@ static void render_player(const obj_player *prev, const obj_player *player) gfx_quads_end(); } - if (client_datas[player->clientid].emoticon_start != -1 && client_datas[player->clientid].emoticon_start + 2 * client_tickspeed() > client_tick()) + if (client_datas[player.clientid].emoticon_start != -1 && client_datas[player.clientid].emoticon_start + 2 * client_tickspeed() > client_tick()) { gfx_texture_set(data->images[IMAGE_EMOTICONS].id); gfx_quads_begin(); - int since_start = client_tick() - client_datas[player->clientid].emoticon_start; - int from_end = client_datas[player->clientid].emoticon_start + 2 * client_tickspeed() - client_tick(); + int since_start = client_tick() - client_datas[player.clientid].emoticon_start; + int from_end = client_datas[player.clientid].emoticon_start + 2 * client_tickspeed() - client_tick(); float a = 1; @@ -1307,7 +1399,7 @@ static void render_player(const obj_player *prev, const obj_player *player) gfx_quads_setcolor(1.0f,1.0f,1.0f,a); // client_datas::emoticon is an offset from the first emoticon - select_sprite(SPRITE_OOP + client_datas[player->clientid].emoticon); + select_sprite(SPRITE_OOP + client_datas[player.clientid].emoticon); gfx_quads_draw(position.x, position.y - 23 - 32*h, 64, 64*h); gfx_quads_end(); } @@ -1726,6 +1818,9 @@ void render_game() } } + local_player_pos = mix(predicted_prev_player.pos, predicted_player.pos, client_intratick()); + //local_player_pos = predicted_player.pos; + // everything updated, do events if(must_process_events) process_events(SNAP_PREV); diff --git a/src/game/game.h b/src/game/game.h index e3e4e99e..2a35bf97 100644 --- a/src/game/game.h +++ b/src/game/game.h @@ -20,6 +20,80 @@ inline float get_angle(vec2 dir) return a; } + +template<typename T> +inline T saturated_add(T min, T max, T current, T modifier) +{ + if(modifier < 0) + { + if(current < min) + return current; + current += modifier; + if(current < min) + current = min; + return current; + } + else + { + if(current > max) + return current; + current += modifier; + if(current > max) + current = max; + return current; + } +} + +void move_point(vec2 *inout_pos, vec2 *inout_vel, float elasticity, int *bounces); +void move_box(vec2 *inout_pos, vec2 *inout_vel, vec2 size, float elasticity); + + +// hooking stuff +enum +{ + HOOK_RETRACTED=-1, + HOOK_IDLE=0, + HOOK_FLYING, + HOOK_GRABBED +}; + +class world_core +{ +public: + world_core() + { + mem_zero(players, sizeof(players)); + } + + class player_core *players[MAX_CLIENTS]; +}; + +class player_core +{ +public: + world_core *world; + + vec2 pos; + vec2 vel; + + vec2 hook_pos; + vec2 hook_dir; + int hook_tick; + int hook_state; + int hooked_player; + + int jumped; + player_input input; + + void tick(); + void move(); + + void read(const obj_player_core *obj_core); + void write(obj_player_core *obj_core); + void quantize(); +}; + + #define LERP(a,b,t) (a + (b-a) * t) #define min(a, b) ( a > b ? b : a) #define max(a, b) ( a > b ? a : b) diff --git a/src/game/game_protocol.h b/src/game/game_protocol.h index cd28b2d5..3ef491ef 100644 --- a/src/game/game_protocol.h +++ b/src/game/game_protocol.h @@ -1,5 +1,22 @@ // NOTE: Be very careful when editing this file as it will change the network version +// --------- PHYSICS TWEAK! -------- +const float ground_control_speed = 7.0f; +const float ground_control_accel = 2.0f; +const float ground_friction = 0.5f; +const float ground_jump_speed = 13.5f; +const float air_control_speed = 3.5f; +const float air_control_accel = 1.2f; +const float air_friction = 0.95f; +const float hook_length = 34*10.0f; +const float hook_fire_speed = 45.0f; +const float hook_drag_accel = 3.0f; +const float hook_drag_speed = 15.0f; +const float gravity = 0.5f; +const float wall_friction = 0.80f; +const float wall_jump_speed_up = ground_jump_speed*0.8f; +const float wall_jump_speed_out = ground_jump_speed*0.8f; + // Network stuff enum { @@ -129,7 +146,19 @@ struct obj_flag int team; }; -struct obj_player + +struct obj_player_core +{ + int x, y; + int vx, vy; + int angle; + + int hook_state; + int hook_x, hook_y; + int hook_dx, hook_dy; +}; + +struct obj_player : public obj_player_core { int local; int clientid; @@ -139,10 +168,6 @@ struct obj_player int armor; int ammocount; - int x, y; - int vx, vy; - int angle; - int weapon; // current active weapon int attacktick; // num attack ticks left of current attack @@ -152,7 +177,5 @@ struct obj_player int latency_flux; int emote; - int hook_active; - int hook_x, hook_y; int team; }; diff --git a/src/game/game_variables.h b/src/game/game_variables.h index c8cf0150..429c18aa 100644 --- a/src/game/game_variables.h +++ b/src/game/game_variables.h @@ -14,6 +14,9 @@ MACRO_CONFIG_INT(scorelimit, 20, 0, 1000) MACRO_CONFIG_INT(timelimit, 0, 0, 1000) MACRO_CONFIG_STR(gametype, 32, "dm") +MACRO_CONFIG_INT(dbg_bots, 0, 0, 7) +MACRO_CONFIG_INT(cl_predict, 1, 0, 1) + MACRO_CONFIG_INT(dynamic_camera, 1, 0, 1) diff --git a/src/game/server/game_server.cpp b/src/game/server/game_server.cpp index ebb35cf1..7ad4ec09 100644 --- a/src/game/server/game_server.cpp +++ b/src/game/server/game_server.cpp @@ -9,26 +9,6 @@ data_container *data = 0x0; -// --------- DEBUG STUFF --------- -const int debug_bots = 3; - -// --------- PHYSICS TWEAK! -------- -const float ground_control_speed = 7.0f; -const float ground_control_accel = 2.0f; -const float ground_friction = 0.5f; -const float ground_jump_speed = 13.5f; -const float air_control_speed = 3.5f; -const float air_control_accel = 1.2f; -const float air_friction = 0.95f; -const float hook_length = 34*10.0f; -const float hook_fire_speed = 45.0f; -const float hook_drag_accel = 3.0f; -const float hook_drag_speed = 15.0f; -const float gravity = 0.5f; -const float wall_friction = 0.80f; -const float wall_jump_speed_up = ground_jump_speed*0.8f; -const float wall_jump_speed_out = ground_jump_speed*0.8f; - 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); @@ -39,134 +19,6 @@ void create_sound(vec2 pos, int sound, int loopflags = 0); void create_targetted_sound(vec2 pos, int sound, int target, int loopflags = 0); class player *intersect_player(vec2 pos0, vec2 pos1, vec2 &new_pos, class entity *notthis = 0); -template<typename T> -T saturated_add(T min, T max, T current, T modifier) -{ - if(modifier < 0) - { - if(current < min) - return current; - current += modifier; - if(current < min) - current = min; - return current; - } - else - { - if(current > max) - return current; - current += modifier; - if(current > max) - current = max; - return current; - } -} - -// TODO: rewrite this smarter! -void move_point(vec2 *inout_pos, vec2 *inout_vel, float elasticity, int *bounces) -{ - if(bounces) - *bounces = 0; - - vec2 pos = *inout_pos; - vec2 vel = *inout_vel; - if(col_check_point(pos + vel)) - { - int affected = 0; - if(col_check_point(pos.x + vel.x, pos.y)) - { - inout_vel->x *= -elasticity; - if(bounces) - (*bounces)++; - affected++; - } - - if(col_check_point(pos.x, pos.y + vel.y)) - { - inout_vel->y *= -elasticity; - if(bounces) - (*bounces)++; - affected++; - } - - if(affected == 0) - { - inout_vel->x *= -elasticity; - inout_vel->y *= -elasticity; - } - } - else - { - *inout_pos = pos + vel; - } -} - -// TODO: rewrite this smarter! -void move_box(vec2 *inout_pos, vec2 *inout_vel, vec2 size, float elasticity) -{ - // do the move - vec2 pos = *inout_pos; - vec2 vel = *inout_vel; - - float distance = length(vel); - int max = (int)distance; - - vec2 offsets[4] = { vec2(-size.x/2, -size.y/2), vec2( size.x/2, -size.y/2), - vec2(-size.x/2, size.y/2), vec2( size.x/2, size.y/2)}; - - if(distance > 0.00001f) - { - vec2 old_pos = pos; - for(int i = 0; i <= max; i++) - { - float amount = i/(float)max; - if(max == 0) - amount = 0; - - vec2 new_pos = pos + vel*amount; // TODO: this row is not nice - - for(int p = 0; p < 4; p++) - { - vec2 np = new_pos+offsets[p]; - vec2 op = old_pos+offsets[p]; - if(col_check_point(np)) - { - int affected = 0; - if(col_check_point(np.x, op.y)) - { - vel.x = -vel.x*elasticity; - pos.x = old_pos.x; - new_pos.x = old_pos.x; - affected++; - } - - if(col_check_point(op.x, np.y)) - { - vel.y = -vel.y*elasticity; - pos.y = old_pos.y; - new_pos.y = old_pos.y; - affected++; - } - - if(!affected) - { - new_pos = old_pos; - pos = old_pos; - vel *= -elasticity; - } - } - } - - old_pos = new_pos; - } - - pos = old_pos; - } - - *inout_pos = pos; - *inout_vel = vel; -} - ////////////////////////////////////////////////// // Event handler ////////////////////////////////////////////////// @@ -784,8 +636,8 @@ void player::reset() release_hooks(); pos = vec2(0.0f, 0.0f); - vel = vec2(0.0f, 0.0f); - direction = vec2(0.0f, 1.0f); + core.vel = vec2(0.0f, 0.0f); + //direction = vec2(0.0f, 1.0f); score = 0; dead = true; spawning = false; @@ -863,7 +715,9 @@ void player::try_respawn() spawning = false; pos = spawnpos; - defered_pos = pos; + + core.pos = pos; + core.hooked_player = -1; health = 10; @@ -873,8 +727,10 @@ void player::try_respawn() set_flag(entity::FLAG_ALIVE); state = STATE_PLAYING; + core.hook_state = HOOK_IDLE; + mem_zero(&input, sizeof(input)); - vel = vec2(0.0f, 0.0f); + core.vel = vec2(0.0f, 0.0f); // init weapons mem_zero(&weapons, sizeof(weapons)); @@ -905,13 +761,14 @@ bool player::is_grounded() // releases the hooked player void player::release_hooked() { - hook_state = HOOK_RETRACTED; - hooked_player = 0x0; + //hook_state = HOOK_RETRACTED; + //hooked_player = 0x0; } // release all hooks to this player void player::release_hooks() { + /* // TODO: loop thru players only for(entity *ent = world.first_entity; ent; ent = ent->next_entity) { @@ -921,11 +778,13 @@ void player::release_hooks() if(p->hooked_player == this) p->release_hooked(); } - } + }*/ } 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 @@ -956,18 +815,18 @@ int player::handle_ninja() if (currentmovetime == 0) { // reset player velocity - vel *= 0.2f; + core.vel *= 0.2f; //return MODIFIER_RETURNFLAGS_OVERRIDEWEAPON; } if (currentmovetime > 0) { // Set player velocity - vel = activationdir * data->weapons[WEAPON_NINJA].velocity; + core.vel = activationdir * data->weapons[WEAPON_NINJA].velocity; vec2 oldpos = pos; - move_box(&defered_pos, &vel, vec2(phys_size, phys_size), 0.0f); + move_box(&core.pos, &core.vel, vec2(phys_size, phys_size), 0.0f); // reset velocity so the client doesn't predict stuff - vel = vec2(0.0f,0.0f); + core.vel = vec2(0.0f,0.0f); if ((currentmovetime % 2) == 0) { create_smoke(pos); @@ -1015,6 +874,8 @@ int player::handle_ninja() int player::handle_weapons() { + vec2 direction = normalize(vec2(input.target_x, input.target_y)); + if(config.stress) { for(int i = 0; i < NUM_WEAPONS; i++) @@ -1175,7 +1036,7 @@ int player::handle_weapons() dir = normalize(target->pos - pos); else dir = vec2(0,-1); - target->vel += dir * 25.0f + vec2(0,-5.0f); + target->core.vel += dir * 25.0f + vec2(0,-5.0f); } } if (data->weapons[active_weapon].ammoregentime) @@ -1228,7 +1089,6 @@ void player::tick() try_respawn(); // TODO: rework the input to be more robust - // TODO: remove this tick count, it feels weird if(dead) { if(server_tick()-die_tick >= server_tickspeed()*5) // auto respawn after 3 sec @@ -1238,205 +1098,30 @@ void player::tick() return; } - // fetch some info - bool grounded = is_grounded(); - int wall_sliding = 0; - direction = normalize(vec2(input.target_x, input.target_y)); + //player_core core; + //core.pos = pos; + //core.jumped = jumped; + core.input = input; + core.tick(); - float max_speed = grounded ? ground_control_speed : air_control_speed; - float accel = grounded ? ground_control_accel : air_control_accel; - float friction = grounded ? ground_friction : air_friction; - - if(!grounded && vel.y > 0) - { - if(input.left && col_check_point((int)(pos.x-phys_size/2)-4, (int)(pos.y))) - wall_sliding = -1; - if(input.right && col_check_point((int)(pos.x+phys_size/2)+4, (int)(pos.y))) - wall_sliding = 1; - } - - if(wall_sliding) - vel.y *= wall_friction; - - // handle movement - if(input.left) - vel.x = saturated_add(-max_speed, max_speed, vel.x, -accel); - if(input.right) - vel.x = saturated_add(-max_speed, max_speed, vel.x, accel); - - if(!input.left && !input.right) - vel.x *= friction; - - // handle jumping - if(input.jump) - { - if(!jumped && (grounded || wall_sliding)) - { - create_sound(pos, SOUND_PLAYER_JUMP); - if(wall_sliding) - { - vel.y = -wall_jump_speed_up; - vel.x = -wall_jump_speed_out*wall_sliding; - } - else - vel.y = -ground_jump_speed; - jumped++; - } - } - else - jumped = 0; - - // do hook - if(input.hook) - { - if(hook_state == HOOK_IDLE) - { - hook_state = HOOK_FLYING; - hook_pos = pos; - hook_dir = direction; - hook_tick = -1; - } - else if(hook_state == HOOK_FLYING) - { - vec2 new_pos = hook_pos+hook_dir*hook_fire_speed; - - // Check against other players first - for(entity *ent = world.first_entity; ent; ent = ent->next_entity) - { - if(ent && ent->objtype == OBJTYPE_PLAYER) - { - player *p = (player*)ent; - if(p != this && !p->dead && distance(p->pos, new_pos) < p->phys_size) - { - hook_state = HOOK_GRABBED; - hooked_player = p; - break; - } - } - } - - if(hook_state == HOOK_FLYING) - { - // check against ground - if(col_intersect_line(hook_pos, new_pos, &new_pos)) - { - hook_state = HOOK_GRABBED; - hook_pos = new_pos; - } - else if(distance(pos, new_pos) > hook_length) - { - hook_state = HOOK_RETRACTED; - } - else - hook_pos = new_pos; - } - - if(hook_state == HOOK_GRABBED) - { - create_sound(pos, SOUND_HOOK_ATTACH); - hook_tick = server_tick(); - } - } - } - else - { - release_hooked(); - hook_state = HOOK_IDLE; - hook_pos = pos; - } - - if(hook_state == HOOK_GRABBED) - { - if(hooked_player) - { - hook_pos = hooked_player->pos; - - // keep players hooked for a max of 1.5sec - if(server_tick() > hook_tick+(server_tickspeed()*3)/2) - release_hooked(); - } - - /*if(hooked_player) - hook_pos = hooked_player->pos; - - float d = distance(pos, hook_pos); - vec2 dir = normalize(pos - hook_pos); - if(d > 10.0f) // TODO: fix tweakable variable - { - float accel = hook_drag_accel * (d/hook_length); - vel.x = saturated_add(-hook_drag_speed, hook_drag_speed, vel.x, -accel*dir.x*0.75f); - vel.y = saturated_add(-hook_drag_speed, hook_drag_speed, vel.y, -accel*dir.y); - }*/ - - // Old version feels much better (to me atleast) - if(distance(hook_pos, pos) > 46.0f) - { - vec2 hookvel = normalize(hook_pos-pos)*hook_drag_accel; - // the hook as more power to drag you up then down. - // this makes it easier to get on top of an platform - if(hookvel.y > 0) - hookvel.y *= 0.3f; - - // the hook will boost it's power if the player wants to move - // in that direction. otherwise it will dampen everything abit - if((hookvel.x < 0 && input.left) || (hookvel.x > 0 && input.right)) - hookvel.x *= 0.95f; - else - hookvel.x *= 0.75f; - - vec2 new_vel = vel+hookvel; - - // check if we are under the legal limit for the hook - if(length(new_vel) < hook_drag_speed || length(new_vel) < length(vel)) - vel = new_vel; // no problem. apply - } - } - - // fix influence of other players, collision + hook - // TODO: loop thru players only - for(entity *ent = world.first_entity; ent; ent = ent->next_entity) - { - if(ent && ent->objtype == OBJTYPE_PLAYER) - { - player *p = (player*)ent; - if(p == this || !(p->flags&FLAG_ALIVE)) - continue; // make sure that we don't nudge our self - - // handle player <-> player collision - float d = distance(pos, p->pos); - vec2 dir = normalize(pos - p->pos); - if(d < phys_size*1.25f) - { - float a = phys_size*1.25f - d; - vel = vel + dir*a; - } - - // handle hook influence - if(p->hooked_player == this) - { - if(d > phys_size*1.50f) // TODO: fix tweakable variable - { - float accel = hook_drag_accel * (d/hook_length); - vel.x = saturated_add(-hook_drag_speed, hook_drag_speed, vel.x, -accel*dir.x); - vel.y = saturated_add(-hook_drag_speed, hook_drag_speed, vel.y, -accel*dir.y); - } - } - } - } // handle weapons int retflags = handle_weapons(); + /* if (!(retflags & (MODIFIER_RETURNFLAGS_OVERRIDEVELOCITY | MODIFIER_RETURNFLAGS_OVERRIDEPOSITION))) { // add gravity - if (!(retflags & MODIFIER_RETURNFLAGS_OVERRIDEGRAVITY)) - vel.y += gravity; + //if (!(retflags & MODIFIER_RETURNFLAGS_OVERRIDEGRAVITY)) + //vel.y += gravity; // do the move defered_pos = pos; - move_box(&defered_pos, &vel, vec2(phys_size, phys_size), 0); - } + move_box(&core.pos, &vel, vec2(phys_size, phys_size), 0); + }*/ + //defered_pos = core.pos; + //jumped = core.jumped; + state = input.state; // Previnput @@ -1446,8 +1131,12 @@ void player::tick() void player::tick_defered() { + core.move(); + core.quantize(); + pos = core.pos; + // apply the new position - pos = defered_pos; + //pos = defered_pos; } void player::die(int killer, int weapon) @@ -1478,13 +1167,14 @@ void player::die(int killer, int weapon) bool player::take_damage(vec2 force, int dmg, int from, int weapon) { - vel += force; + core.vel += force; // player only inflicts half damage on self if(from == client_id) dmg = max(1, dmg/2); - if (gameobj->gametype == GAMETYPE_TDM && from >= 0 && players[from].team == team) + // CTF and TDM, + if (gameobj->gametype != GAMETYPE_DM && from >= 0 && players[from].team == team) return false; damage_taken++; @@ -1567,10 +1257,15 @@ void player::snap(int snaping_client) { obj_player *player = (obj_player *)snap_new_item(OBJTYPE_PLAYER, client_id, sizeof(obj_player)); - player->x = (int)pos.x; - player->y = (int)pos.y; - player->vx = (int)vel.x; - player->vy = (int)vel.y; + core.write(player); + + if(snaping_client != client_id) + { + player->vx = 0; // make sure that we don't send these to clients who don't need them + player->vy = 0; + player->hook_dx = 0; + player->hook_dy = 0; + } if (emote_stop < server_tick()) { @@ -1613,21 +1308,6 @@ void player::snap(int snaping_client) player->emote = EMOTE_BLINK; } - player->hook_active = hook_state>0?1:0; - player->hook_x = (int)hook_pos.x; - player->hook_y = (int)hook_pos.y; - - float a = 0; - if(input.target_x == 0) - a = atan((float)input.target_y); - else - a = atan((float)input.target_y/(float)input.target_x); - - if(input.target_x < 0) - a = a+pi; - - player->angle = (int)(a*256.0f); - player->score = score; player->team = team; @@ -2011,7 +1691,7 @@ void mods_tick() if(world.paused) // make sure that the game object always updates gameobj->tick(); - if(debug_bots) + if(config.dbg_bots) { static int count = 0; if(count >= 0) @@ -2019,13 +1699,14 @@ void mods_tick() count++; if(count == 10) { - for(int i = 0; i < debug_bots ; i++) + for(int i = 0; i < config.dbg_bots ; i++) { mods_client_enter(MAX_CLIENTS-i-1); strcpy(players[MAX_CLIENTS-i-1].name, "(bot)"); if(gameobj->gametype != GAMETYPE_DM) - players[MAX_CLIENTS-i-1].team = count&1; + players[MAX_CLIENTS-i-1].team = i&1; } + count = -1; } } @@ -2187,7 +1868,15 @@ void mods_init() players = new player[MAX_CLIENTS]; gameobj = new gameobject; + + // setup core world + for(int i = 0; i < MAX_CLIENTS; i++) + { + players[i].core.world = &world.core; + world.core.players[i] = &players[i].core; + } + // int start, num; map_get_type(MAPRES_ITEM, &start, &num); diff --git a/src/game/server/game_server.h b/src/game/server/game_server.h index b691e0de..56f668f6 100644 --- a/src/game/server/game_server.h +++ b/src/game/server/game_server.h @@ -85,6 +85,8 @@ public: 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); @@ -229,9 +231,9 @@ public: int last_action; // we need a defered position so we can handle the physics correctly - vec2 defered_pos; - vec2 vel; - vec2 direction; + //vec2 defered_pos; + //vec2 vel; + //vec2 direction; // int client_id; @@ -269,21 +271,14 @@ public: int latency_avg; int latency_min; int latency_max; - - // hooking stuff - enum - { - HOOK_RETRACTED=-1, - HOOK_IDLE=0, - HOOK_FLYING, - HOOK_GRABBED - }; - int hook_state; - int hook_tick; - player *hooked_player; - vec2 hook_pos; - vec2 hook_dir; + player_core core; + + //int hook_state; + //int hook_tick; + //player *hooked_player; + //vec2 hook_pos; + //vec2 hook_dir; // player(); |