From 8fd19cddc056bc5aad40c9af37ef88fe4794922e Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Wed, 21 Aug 2019 15:49:35 -0700 Subject: [PATCH] Propagation of some of the weapon variables needed for prediction. Resetting of map entities for when a solo player spawns (risky, but needs testing!) --- Source/client/predict.c | 22 ++++---- Source/client/valve/hud_weaponselect.c | 2 + Source/client/valve/player.c | 74 ++++++++++++++++++-------- Source/client/view.c | 2 +- Source/server/cstrike/main.c | 1 + Source/server/flashlight.c | 4 ++ Source/server/scihunt/client.c | 13 +++++ Source/server/scihunt/server.c | 17 +++++- Source/server/valve/client.c | 13 +++++ Source/server/valve/player.c | 5 +- Source/server/valve/server.c | 15 ++++++ Source/shared/pmove.c | 12 ++--- Source/shared/scihunt/player.cpp | 4 +- Source/shared/scihunt/w_cannon.c | 8 +-- Source/shared/scihunt/w_chainsaw.c | 8 +-- Source/shared/scihunt/w_hammer.c | 8 +-- Source/shared/valve/player.cpp | 2 + Source/shared/valve/w_crowbar.c | 2 +- Source/shared/valve/w_handgrenade.c | 2 +- Source/shared/valve/weapon_common.c | 4 +- 20 files changed, 158 insertions(+), 60 deletions(-) diff --git a/Source/client/predict.c b/Source/client/predict.c index 497edea2..ef065f41 100644 --- a/Source/client/predict.c +++ b/Source/client/predict.c @@ -22,14 +22,14 @@ void Predict_PreFrame(player pl) pl.netflags = pl.flags; pl.netjumptime = pl.jumptime; pl.netteleport_time = pl.teleport_time; - + #ifdef VALVE - //pl.net_w_attack_next = pl.w_attack_next; - //pl.net_w_idle_next = pl.w_idle_next; + pl.net_w_attack_next = pl.w_attack_next; + pl.net_w_idle_next = pl.w_idle_next; pl.net_ammo1 = pl.a_ammo1; pl.net_ammo2 = pl.a_ammo2; pl.net_ammo3 = pl.a_ammo3; - //pl.net_weapontime = pSeat->eViewModel.frame1time; + pl.net_weapontime = pl.weapontime; #endif //self.netpmove_flags = self.pmove_flags; @@ -37,8 +37,9 @@ void Predict_PreFrame(player pl) //we want to predict an exact copy of the data in the new packet /*for (; self.pmove_frame <= servercommandframe; self.pmove_frame++) { float flSuccess = getinputstate(self.pmove_frame);*/ - for ( int i = servercommandframe + 1; i <= clientcommandframe; i++ ) { + for ( int i = pl.sequence + 1; i <= clientcommandframe; i++ ) { float flSuccess = getinputstate( i ); + input_sequence = i; if (flSuccess == FALSE) { continue; } @@ -60,8 +61,8 @@ void Predict_PreFrame(player pl) Predict_PostFrame We're part way through parsing new player data. -Propagate our pmove state to whatever the current frame before its stomped on -(so any non-networked state updates locally). +Rewind our pmove state back to before we started predicting. +(to give consistent state instead of accumulating errors) ================= */ void Predict_PostFrame(player pl) @@ -73,13 +74,12 @@ void Predict_PostFrame(player pl) pl.teleport_time = pl.netteleport_time; #ifdef VALVE - //pl.w_attack_next = pl.net_w_attack_next; - //pl.w_idle_next = pl.net_w_idle_next; + pl.w_attack_next = pl.net_w_attack_next; + pl.w_idle_next = pl.net_w_idle_next; pl.a_ammo1 = pl.net_ammo1; pl.a_ammo2 = pl.net_ammo2; pl.a_ammo3 = pl.net_ammo3; - //pSeat->eViewModel.frame1time = pl.net_weapontime; - //pSeat->eViewModel.frame2time = pl.net_weapontime; + pl.weapontime = pl.net_weapontime; #endif //self.pmove_flags = self.netpmove_flags; diff --git a/Source/client/valve/hud_weaponselect.c b/Source/client/valve/hud_weaponselect.c index d262a3a1..708b77bc 100644 --- a/Source/client/valve/hud_weaponselect.c +++ b/Source/client/valve/hud_weaponselect.c @@ -70,6 +70,8 @@ void HUD_DrawWeaponSelect_Back(void) void HUD_DrawWeaponSelect_Trigger(void) { + player pl = (player)pSeat->ePlayer; + pl.activeweapon = pSeat->fHUDWeaponSelected; sendevent("PlayerSwitchWeapon", "f", pSeat->fHUDWeaponSelected); sound(pSeat->ePlayer, CHAN_ITEM, "common/wpn_select.wav", 0.5f, ATTN_NONE); pSeat->fHUDWeaponSelected = pSeat->fHUDWeaponSelectTime = 0; diff --git a/Source/client/valve/player.c b/Source/client/valve/player.c index 801bee99..5cbefe51 100644 --- a/Source/client/valve/player.c +++ b/Source/client/valve/player.c @@ -6,6 +6,19 @@ * ****/ +//FOR DEBUGGING ONLY, remove when prediction is trusted (along with the extra network bloat). +static void warnifdiff(string name, __inout float expected, float got) +{ + //this should only fire from prediction misses. + //this hopefully only happens when the server's anti-time-banking logic does its thing, or for things caused by other players/ents getting in the way. + + if (expected != got) + print(sprintf("%s differs, expected %g, got %g\n", name, expected, got)); + + //enable the following line if you want to see if it actually makes a difference. + //expected = got; +} + void Player_ReadEntity(float flIsNew) { player pl = (player)self; @@ -16,37 +29,56 @@ void Player_ReadEntity(float flIsNew) pl.drawmask = MASK_ENGINE; pl.customphysics = Empty; setsize( pl, VEC_HULL_MIN, VEC_HULL_MAX ); - } - pl.modelindex = readshort(); + print(sprintf("Player %g is csqc ent %i\n", pl.entnum, pl)); + } + else + { + if (pl.entnum == player_localentnum) //FIXME: splitscreen + { + pSeat = &seats[0]; //FIXME: splitscreen + for (int i = pl.sequence+1; i <= servercommandframe; i++) + { + if (!getinputstate(i)) + break; //erk?... too old? + input_sequence = i; + QPhysics_Run(pl); + } + + //any differences in things that are read below are now officially from prediction misses. + } + } + pl.sequence = servercommandframe; + + pl.modelindex = readshort(); //make conditional pl.origin[0] = readcoord(); pl.origin[1] = readcoord(); - pl.origin[2] = readcoord(); + pl.origin[2] = readcoord(); //make conditional pl.pitch = readfloat(); pl.angles[1] = readfloat(); pl.angles[2] = readfloat(); pl.velocity[0] = readcoord(); pl.velocity[1] = readcoord(); pl.velocity[2] = readcoord(); - pl.flags = readfloat(); - pl.activeweapon = readbyte(); - pl.weapontime = readfloat(); - pl.g_items = readfloat(); - pl.health = readbyte(); - pl.armor = readbyte(); - pl.movetype = readbyte(); - pl.view_ofs[2] = readfloat(); - pl.viewzoom = readfloat(); - pl.jumptime = readfloat(); - pl.teleport_time = readfloat(); + pl.flags = readfloat(); //make mostly conditional + pl.activeweapon = readbyte(); //make conditional + warnifdiff("weapontime", pl.weapontime, readfloat()); //remove + pl.g_items = readfloat(); //make conditional + pl.health = readbyte(); //make conditional + pl.armor = readbyte(); //make conditional + pl.movetype = readbyte(); //make conditional + pl.view_ofs[2] = readfloat(); //make conditional + pl.viewzoom = readfloat(); //remove? or make conditional + warnifdiff("jumptime", pl.jumptime, readfloat()); //remove + warnifdiff("teletime", pl.teleport_time, readfloat()); //remove - pl.baseframe = readbyte(); - pl.frame = readbyte(); + pl.baseframe = readbyte(); //make conditional + pl.frame = readbyte(); //make conditional - pl.a_ammo1 = readbyte(); - pl.a_ammo2 = readbyte(); - pl.a_ammo3 = readbyte(); - //pl.w_attack_next = readfloat(); - //pl.w_idle_next = readfloat(); + pl.a_ammo1 = readbyte(); //make conditional + pl.a_ammo2 = readbyte(); //make conditional + pl.a_ammo3 = readbyte(); //make conditional + warnifdiff("attack_next", pl.w_attack_next, readfloat()); //remove + warnifdiff("idle_next", pl.w_idle_next, readfloat()); //remove setorigin( pl, pl.origin ); } diff --git a/Source/client/view.c b/Source/client/view.c index dbd53e6f..ccc1701d 100644 --- a/Source/client/view.c +++ b/Source/client/view.c @@ -193,7 +193,7 @@ void View_DrawViewModel(void) float fBaseTime = eViewModel.frame1time; eViewModel.frame2time = pl.weapontime; eViewModel.frame1time = pl.weapontime; - //processmodelevents(eViewModel.modelindex, eViewModel.frame, fBaseTime, eViewModel.frame1time, Event_ProcessModel); + processmodelevents(eViewModel.modelindex, eViewModel.frame, fBaseTime, eViewModel.frame1time, Event_ProcessModel); } makevectors(view_angles); diff --git a/Source/server/cstrike/main.c b/Source/server/cstrike/main.c index 3581fcaa..46fb3dda 100644 --- a/Source/server/cstrike/main.c +++ b/Source/server/cstrike/main.c @@ -231,6 +231,7 @@ void Game_Worldspawn(void) precache_model("models/player/vip/vip.mdl"); precache_model("models/w_c4.mdl"); + precache_sound("misc/null.wav"); precache_sound("hostage/hos1.wav"); precache_sound("hostage/hos2.wav"); precache_sound("hostage/hos3.wav"); diff --git a/Source/server/flashlight.c b/Source/server/flashlight.c index 4cbe4dab..15c4b677 100644 --- a/Source/server/flashlight.c +++ b/Source/server/flashlight.c @@ -14,6 +14,10 @@ void Flashlight_Toggle(void) } } + if (self.health <= 0) { + return; + } + if (self.flags & FL_FLASHLIGHT) { self.flags &= ~FL_FLASHLIGHT; } else { diff --git a/Source/server/scihunt/client.c b/Source/server/scihunt/client.c index c5703f09..06724f4e 100644 --- a/Source/server/scihunt/client.c +++ b/Source/server/scihunt/client.c @@ -11,6 +11,19 @@ void Empty(void) {} void Game_ClientConnect(void) { bprint(PRINT_HIGH, sprintf("%s connected\n", self.netname)); + + int playercount = 0; + for (entity eFind = world; (eFind = find(eFind, classname, "player"));) { + playercount++; + } + + /* We're the first. */ + if (playercount == 0) { + for (entity a = world; (a = findfloat(a, gflags, GF_CANRESPAWN));) { + CBaseEntity caw = (CBaseEntity)a; + caw.Respawn(); + } + } } void Game_ClientDisconnect(void) diff --git a/Source/server/scihunt/server.c b/Source/server/scihunt/server.c index abf78b1e..20843e51 100644 --- a/Source/server/scihunt/server.c +++ b/Source/server/scihunt/server.c @@ -19,6 +19,21 @@ float Game_ConsoleCmd(string cmd) void Game_Worldspawn(void) { precache_model("models/player.mdl"); - Weapons_Init(); + precache_model("models/w_weaponbox.mdl"); + + precache_sound("misc/null.wav"); + precache_sound("fvox/flatline.wav"); + + /* TODO: Scan and precache models/player/.mdl */ + precache_model("models/player/barney/barney.mdl"); + precache_model("models/player/gman/gman.mdl"); + precache_model("models/player/gordon/gordon.mdl"); + precache_model("models/player/hgrunt/hgrunt.mdl"); + precache_model("models/player/scientist/scientist.mdl"); + precache_model("models/player/zombie/zombie.mdl"); + precache_model("models/player/helmet/helmet.mdl"); + precache_model("models/player/recon/recon.mdl"); + precache_model("models/player/robo/robo.mdl"); + Weapons_Init(); SHData_Parse(mapname); } diff --git a/Source/server/valve/client.c b/Source/server/valve/client.c index 49570bd8..87c524fb 100644 --- a/Source/server/valve/client.c +++ b/Source/server/valve/client.c @@ -11,6 +11,19 @@ void Empty(void) {} void Game_ClientConnect(void) { bprint(PRINT_HIGH, sprintf("%s connected\n", self.netname)); + + int playercount = 0; + for (entity eFind = world; (eFind = find(eFind, classname, "player"));) { + playercount++; + } + + /* We're the first. */ + if (playercount == 0) { + for (entity a = world; (a = findfloat(a, gflags, GF_CANRESPAWN));) { + CBaseEntity caw = (CBaseEntity)a; + caw.Respawn(); + } + } } void Game_ClientDisconnect(void) diff --git a/Source/server/valve/player.c b/Source/server/valve/player.c index 3613e9c2..0121c1cd 100644 --- a/Source/server/valve/player.c +++ b/Source/server/valve/player.c @@ -19,6 +19,7 @@ void Player_Death(int hit) pl.movetype = MOVETYPE_NONE; pl.solid = SOLID_NOT; pl.takedamage = DAMAGE_NO; + pl.flags &= ~FL_FLASHLIGHT; pl.health = pl.armor = pl.activeweapon = pl.g_items = 0; pl.think = PutClientInServer; @@ -138,8 +139,8 @@ float Player_SendEntity(entity ePEnt, float fChanged) WriteByte(MSG_ENTITY, pl.a_ammo1); WriteByte(MSG_ENTITY, pl.a_ammo2); WriteByte(MSG_ENTITY, pl.a_ammo3); - //WriteFloat(MSG_ENTITY, pl.w_attack_next); - //WriteFloat(MSG_ENTITY, pl.w_idle_next); + WriteFloat(MSG_ENTITY, pl.w_attack_next); + WriteFloat(MSG_ENTITY, pl.w_idle_next); return TRUE; } diff --git a/Source/server/valve/server.c b/Source/server/valve/server.c index f40153b7..3722b25f 100644 --- a/Source/server/valve/server.c +++ b/Source/server/valve/server.c @@ -19,5 +19,20 @@ float Game_ConsoleCmd(string cmd) void Game_Worldspawn(void) { precache_model("models/player.mdl"); + precache_model("models/w_weaponbox.mdl"); + + precache_sound("misc/null.wav"); + precache_sound("fvox/flatline.wav"); + + /* TODO: Scan and precache models/player/.mdl */ + precache_model("models/player/barney/barney.mdl"); + precache_model("models/player/gman/gman.mdl"); + precache_model("models/player/gordon/gordon.mdl"); + precache_model("models/player/hgrunt/hgrunt.mdl"); + precache_model("models/player/scientist/scientist.mdl"); + precache_model("models/player/zombie/zombie.mdl"); + precache_model("models/player/helmet/helmet.mdl"); + precache_model("models/player/recon/recon.mdl"); + precache_model("models/player/robo/robo.mdl"); Weapons_Init(); } diff --git a/Source/shared/pmove.c b/Source/shared/pmove.c index 2126bbd6..8553cc15 100644 --- a/Source/shared/pmove.c +++ b/Source/shared/pmove.c @@ -721,15 +721,9 @@ void PMove_Run(void) #ifdef VALVE player pl = (player)self; - pl.w_attack_next -= input_timelength; - pl.w_idle_next -= input_timelength; - pl.weapontime += input_timelength; - if (pl.w_attack_next <= 0) { - pl.w_attack_next = 0; - } - if (pl.w_idle_next <= 0) { - pl.w_idle_next = 0; - } + pl.w_attack_next = max(0, pl.w_attack_next-input_timelength); + pl.w_idle_next = max(0, pl.w_idle_next-input_timelength); + pl.weapontime += input_timelength; #endif Game_Input(); diff --git a/Source/shared/scihunt/player.cpp b/Source/shared/scihunt/player.cpp index f94e119f..650f6389 100644 --- a/Source/shared/scihunt/player.cpp +++ b/Source/shared/scihunt/player.cpp @@ -1,4 +1,4 @@ - +int input_sequence; class player { float health; @@ -56,6 +56,8 @@ class player int net_ammo1; int net_ammo2; int net_ammo3; + int sequence; + virtual void() gun_offset; virtual void() draw; virtual float() predraw; diff --git a/Source/shared/scihunt/w_cannon.c b/Source/shared/scihunt/w_cannon.c index aabe3c60..89713528 100644 --- a/Source/shared/scihunt/w_cannon.c +++ b/Source/shared/scihunt/w_cannon.c @@ -28,9 +28,11 @@ void w_cannon_precache(void) precache_sound("cannon/fire.wav"); precache_sound("cannon/open.wav"); } -string w_cannon_vmodel(void) +void w_cannon_updateammo(player pl) { - return "models/v_cannon.mdl"; +#ifdef SSQC + Weapons_UpdateAmmo(pl, pl.cannon_mag, pl.ammo_buckshot, __NULL__); +#endif } string w_cannon_pmodel(void) { @@ -218,7 +220,7 @@ weapon_t w_cannon = w_cannon_crosshair, w_cannon_precache, w_cannon_pickup, - w_cannon_vmodel, + w_cannon_updateammo, __NULL__, w_cannon_pmodel, w_cannon_deathmsg, diff --git a/Source/shared/scihunt/w_chainsaw.c b/Source/shared/scihunt/w_chainsaw.c index 0509637f..b60f8f74 100644 --- a/Source/shared/scihunt/w_chainsaw.c +++ b/Source/shared/scihunt/w_chainsaw.c @@ -29,9 +29,11 @@ void w_chainsaw_precache(void) precache_model("models/p_saw.mdl"); } -string w_chainsaw_vmodel(void) +void w_chainsaw_updateammo(player pl) { - return "models/v_chainsaw.mdl"; +#ifdef SSQC + Weapons_UpdateAmmo(pl, __NULL__, __NULL__, __NULL__); +#endif } string w_chainsaw_pmodel(void) { @@ -157,7 +159,7 @@ weapon_t w_chainsaw = __NULL__, w_chainsaw_precache, __NULL__, - w_chainsaw_vmodel, + w_chainsaw_updateammo, __NULL__, w_chainsaw_pmodel, w_chainsaw_deathmsg, diff --git a/Source/shared/scihunt/w_hammer.c b/Source/shared/scihunt/w_hammer.c index 5154f9f4..1a2cbfb2 100644 --- a/Source/shared/scihunt/w_hammer.c +++ b/Source/shared/scihunt/w_hammer.c @@ -30,9 +30,11 @@ void w_hammer_precache(void) precache_model("models/v_hammer.mdl"); } -string w_hammer_vmodel(void) +void w_hammer_updateammo(player pl) { - return "models/v_hammer.mdl"; +#ifdef SSQC + Weapons_UpdateAmmo(pl, __NULL__, __NULL__, __NULL__); +#endif } string w_hammer_pmodel(void) { @@ -217,7 +219,7 @@ weapon_t w_hammer = __NULL__, w_hammer_precache, __NULL__, - w_hammer_vmodel, + w_hammer_updateammo, __NULL__, w_hammer_pmodel, w_hammer_deathmsg, diff --git a/Source/shared/valve/player.cpp b/Source/shared/valve/player.cpp index 84e410d3..6c5062e2 100644 --- a/Source/shared/valve/player.cpp +++ b/Source/shared/valve/player.cpp @@ -1,3 +1,4 @@ +int input_sequence; class player { float health; @@ -53,6 +54,7 @@ class player int net_ammo1; int net_ammo2; int net_ammo3; + int sequence; virtual void() gun_offset; virtual void() draw; diff --git a/Source/shared/valve/w_crowbar.c b/Source/shared/valve/w_crowbar.c index 38bafae9..f7e0ac81 100644 --- a/Source/shared/valve/w_crowbar.c +++ b/Source/shared/valve/w_crowbar.c @@ -73,7 +73,7 @@ void w_crowbar_primary(void) vector src = pl.origin + pl.view_ofs; traceline(src, src + (v_forward * 32), FALSE, pl); - int r = floor(random(0,3)); + int r = (float)input_sequence%3; switch (r) { case 0: Weapons_ViewAnimation(trace_fraction >= 1 ? CROWBAR_ATTACK1MISS:CROWBAR_ATTACK1HIT); diff --git a/Source/shared/valve/w_handgrenade.c b/Source/shared/valve/w_handgrenade.c index 904c1d6a..c32a957b 100644 --- a/Source/shared/valve/w_handgrenade.c +++ b/Source/shared/valve/w_handgrenade.c @@ -110,7 +110,7 @@ void w_handgrenade_throw(void) void w_handgrenade_draw(void) { - Weapons_SetModel("models/v_crowbar.mdl"); + Weapons_SetModel("models/v_grenade.mdl"); Weapons_ViewAnimation(HANDGRENADE_DRAW); #ifdef SSQC player pl = (player)self; diff --git a/Source/shared/valve/weapon_common.c b/Source/shared/valve/weapon_common.c index 19b2ea95..e91a33c0 100644 --- a/Source/shared/valve/weapon_common.c +++ b/Source/shared/valve/weapon_common.c @@ -38,9 +38,7 @@ void Weapons_Draw(void) if (g_weapons[i].draw != __NULL__) { g_weapons[i].draw(); } -#ifdef CSQC - View_UpdateWeapon(pSeat->eViewModel, pSeat->eMuzzleflash); -#else +#ifdef SSQC if (g_weapons[i].updateammo != __NULL__) { g_weapons[i].updateammo(pl); }