From a3ecd78f17b06a91e0993ab95f3e3118b8099a31 Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Mon, 10 May 2021 08:14:10 +0200 Subject: [PATCH] CBaseMonster: support for spawnflag MSF_IGNOREPLAYER (64). --- base/src/client/cmds.qc | 4 +- base/src/client/entities.qc | 4 +- base/src/server/damage.qc | 14 +-- base/src/server/gamerules_multiplayer.qc | 4 +- base/src/server/rules.qc | 2 +- base/src/shared/input.qc | 34 ++---- base/src/shared/player.qc | 6 +- base/src/shared/pmove.qc | 2 +- base/src/shared/weapon_common.h | 5 +- base/src/shared/weapon_common.qc | 131 ++++++++++------------- src/client/entry.qc | 21 +--- src/client/predict.qc | 48 +++++++++ src/gs-entbase/server/basemonster.h | 2 +- src/gs-entbase/server/basemonster.qc | 3 + src/menu-fn/entry.qc | 6 +- src/menu-fn/m_customgame.qc | 18 ++-- src/menu-fn/modserver.qc | 2 +- src/menu-fn/servers.qc | 6 +- src/menu-fn/tcp.qc | 6 +- src/menu-fn/util.qc | 4 +- src/plugins/connectsounds.qc | 4 +- src/shared/player.qc | 65 ++++++++++- 22 files changed, 227 insertions(+), 164 deletions(-) diff --git a/base/src/client/cmds.qc b/base/src/client/cmds.qc index f4d81351..3e7d95b4 100644 --- a/base/src/client/cmds.qc +++ b/base/src/client/cmds.qc @@ -21,7 +21,7 @@ ClientGame_ConsoleCommand(void) { switch(argv(0)) { default: - return FALSE; + return (0); } - return TRUE; + return (1); } diff --git a/base/src/client/entities.qc b/base/src/client/entities.qc index c96e2e1d..763a69e8 100644 --- a/base/src/client/entities.qc +++ b/base/src/client/entities.qc @@ -19,10 +19,10 @@ ClientGame_EntityUpdate(float id, float new) { switch (id) { default: - return FALSE; + return (0); } - return TRUE; + return (1); } void diff --git a/base/src/server/damage.qc b/base/src/server/damage.qc index fdf070c4..0c2eddcc 100644 --- a/base/src/server/damage.qc +++ b/base/src/server/damage.qc @@ -94,31 +94,31 @@ Damage_CheckTrace(entity t, vector vecHitPos) { /* We're lazy. Who cares */ if (t.solid == SOLID_BSP) { - return TRUE; + return (1); } traceline(vecHitPos, t.origin, 1, self); if (trace_fraction == 1) { - return TRUE; + return (1); } traceline(vecHitPos, t.origin + [15,15,0], 1, self); if (trace_fraction == 1) { - return TRUE; + return (1); } traceline(vecHitPos, t.origin + [-15,-15,0], 1, self); if (trace_fraction == 1) { - return TRUE; + return (1); } traceline(vecHitPos, t.origin + [-15,15,0], 1, self); if (trace_fraction == 1) { - return TRUE; + return (1); } traceline(vecHitPos, t.origin + [15,-15,0], 1, self); if (trace_fraction == 1) { - return TRUE; + return (1); } - return FALSE; + return (0); } /* even more pain and suffering, mostly used for explosives */ diff --git a/base/src/server/gamerules_multiplayer.qc b/base/src/server/gamerules_multiplayer.qc index 1ccb2fc8..acd26080 100644 --- a/base/src/server/gamerules_multiplayer.qc +++ b/base/src/server/gamerules_multiplayer.qc @@ -109,8 +109,8 @@ MultiplayerRules::ConsoleCommand(base_player pp, string cmd) Bot_AddQuick(); break; default: - return FALSE; + return (0); } - return TRUE; + return (1); } diff --git a/base/src/server/rules.qc b/base/src/server/rules.qc index e6b76f0a..42178bda 100644 --- a/base/src/server/rules.qc +++ b/base/src/server/rules.qc @@ -16,5 +16,5 @@ int Rules_IsTeamPlay(void) { - return cvar("teamplay"); + return (int)(cvar("teamplay")); } diff --git a/base/src/shared/input.qc b/base/src/shared/input.qc index e43aa5fd..d896095e 100644 --- a/base/src/shared/input.qc +++ b/base/src/shared/input.qc @@ -14,13 +14,6 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* -================= -Input_Handle - -Handles impulse and whatnot -================= -*/ void Game_Input(void) { @@ -32,34 +25,23 @@ Game_Input(void) return; } - if (self.impulse == 100) { - Flashlight_Toggle(); - } - - if (input_buttons & INPUT_BUTTON5) { + if (input_buttons & INPUT_BUTTON5) Player_UseDown(); - } else { + else Player_UseUp(); - } - if (cvar("sv_cheats") == 1) { - player pl = (player)self; - if (self.impulse == 101) { - pl.health = 100; - pl.armor = 100; - } - } + if (self.impulse == 100) + Flashlight_Toggle(); self.impulse = 0; #endif - if (input_buttons & INPUT_BUTTON0) { + if (input_buttons & INPUT_BUTTON0) Weapons_Primary(); - } else if (input_buttons & INPUT_BUTTON4) { + else if (input_buttons & INPUT_BUTTON4) Weapons_Reload(); - } else if (input_buttons & INPUT_BUTTON3) { + else if (input_buttons & INPUT_BUTTON3) Weapons_Secondary(); - } else { + else Weapons_Release(); - } } diff --git a/base/src/shared/player.qc b/base/src/shared/player.qc index 571aa6f9..95f4230f 100644 --- a/base/src/shared/player.qc +++ b/base/src/shared/player.qc @@ -121,12 +121,12 @@ player::SendEntity(entity ePEnt, float fChanged) { /* remove our entity to other clients if we're dead */ if (health <= 0 && ePEnt != this) { - return FALSE; + return (0); } /* target client isn't real, they have no client-side. abandon */ if (clienttype(ePEnt) != CLIENTTYPE_REAL) { - return FALSE; + return (0); } /* other players don't need to know about these attributes */ @@ -142,6 +142,6 @@ player::SendEntity(entity ePEnt, float fChanged) /* the generic client attributes */ base_player::SendEntity(ePEnt, fChanged); - return TRUE; + return (1); } #endif diff --git a/base/src/shared/pmove.qc b/base/src/shared/pmove.qc index f7bf4625..b22e1c81 100644 --- a/base/src/shared/pmove.qc +++ b/base/src/shared/pmove.qc @@ -24,7 +24,7 @@ float GamePMove_Maxspeed(player target) { - return (target.flags & FL_CROUCHING) ? 135 : 270; + return ((target.flags & FL_CROUCHING) ? 135 : 270); } void diff --git a/base/src/shared/weapon_common.h b/base/src/shared/weapon_common.h index ece0d3f2..555cf900 100644 --- a/base/src/shared/weapon_common.h +++ b/base/src/shared/weapon_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020 Marco Hladik + * Copyright (c) 2016-2021 Marco Hladik * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -45,6 +45,8 @@ void Weapons_Secondary(void); void Weapons_Reload(void); void Weapons_Release(void); +float Weapons_GetAim(int); +void Weapons_Reload(void); void Weapons_DrawCrosshair(void); void Weapons_MakeVectors(void); vector Weapons_GetCameraPos(void); @@ -53,6 +55,7 @@ void Weapons_ViewPunchAngle(vector); int Weapons_IsPresent(player, int); void Weapons_SetModel(string); void Weapons_SetGeomset(string); +void Weapons_UpdateAmmo(base_player, int, int, int); int Weapons_GetAnimation(void); #ifdef CLIENT diff --git a/base/src/shared/weapon_common.qc b/base/src/shared/weapon_common.qc index f139fc42..746900d7 100644 --- a/base/src/shared/weapon_common.qc +++ b/base/src/shared/weapon_common.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020 Marco Hladik + * Copyright (c) 2016-2021 Marco Hladik * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,10 +14,6 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifdef SERVER -void Decals_Init(void); -#endif - void Weapons_Init(void) { @@ -47,11 +43,9 @@ Weapons_Init(void) fclose(fh); }*/ - for (int i = 0; i < g_weapons.length; i++) { - if (g_weapons[i].precache != __NULL__) { + for (int i = 0; i < g_weapons.length; i++) + if (g_weapons[i].precache != __NULL__) g_weapons[i].precache(); - } - } } void @@ -80,17 +74,21 @@ Weapons_Draw(void) pl.w_idle_next = 2.5f; pl.viewzoom = 1.0f; +#ifdef CLIENT + entity eold = self; + self = pSeat->m_pWeaponFX; + spawnfunc_CBaseFX(); + self = eold; +#endif + /* make sure this is all wiped */ pl.a_ammo1 = pl.a_ammo2 = pl.a_ammo3 = 0; - if (g_weapons[i].draw != __NULL__) { + if (g_weapons[i].draw != __NULL__) g_weapons[i].draw(); - } -#ifdef SERVER - if (g_weapons[i].updateammo != __NULL__) { + + if (g_weapons[i].updateammo != __NULL__) g_weapons[i].updateammo(pl); - } -#endif } void @@ -98,9 +96,9 @@ Weapons_Holster(void) { player pl = (player)self; int i = pl.activeweapon; - if (g_weapons[i].holster != __NULL__) { + + if (g_weapons[i].holster != __NULL__) g_weapons[i].holster(); - } } void @@ -112,15 +110,22 @@ Weapons_Primary(void) if (pl.flags & FL_NOATTACK) return; - if (g_weapons[i].primary != __NULL__) { + if (g_weapons[i].primary != __NULL__) g_weapons[i].primary(); - } -#ifdef SERVER - if (g_weapons[i].updateammo != __NULL__) { + if (g_weapons[i].updateammo != __NULL__) g_weapons[i].updateammo(pl); - } -#endif +} + +void +Weapons_AmmoUpdate(entity target) +{ + player pl = (player)target; + int i = pl.activeweapon; + + if (g_weapons[i].updateammo != __NULL__) + g_weapons[i].updateammo(pl); + } void @@ -132,14 +137,11 @@ Weapons_Secondary(void) if (pl.flags & FL_NOATTACK) return; - if (g_weapons[i].secondary != __NULL__) { + if (g_weapons[i].secondary != __NULL__) g_weapons[i].secondary(); - } -#ifdef SERVER - if (g_weapons[i].updateammo != __NULL__) { + + if (g_weapons[i].updateammo != __NULL__) g_weapons[i].updateammo(pl); - } -#endif } void @@ -151,14 +153,11 @@ Weapons_Reload(void) if (pl.flags & FL_NOATTACK) return; - if (g_weapons[i].reload != __NULL__) { + if (g_weapons[i].reload != __NULL__) g_weapons[i].reload(); - } -#ifdef SERVER - if (g_weapons[i].updateammo != __NULL__) { + + if (g_weapons[i].updateammo != __NULL__) g_weapons[i].updateammo(pl); - } -#endif } void @@ -166,10 +165,10 @@ Weapons_Release(void) { player pl = (player)self; int i = pl.activeweapon; - if (g_weapons[i].release != __NULL__) { + + if (g_weapons[i].release != __NULL__) g_weapons[i].release(); - } - + pl.gflags &= ~GF_SEMI_TOGGLED; } @@ -178,60 +177,53 @@ Weapons_DrawCrosshair(void) { player pl = (player)self; int i = pl.activeweapon; - if (g_weapons[i].crosshair != __NULL__) { + + if (g_weapons[i].crosshair != __NULL__) g_weapons[i].crosshair(); - } } string Weapons_GetWorldmodel(int id) { - if (g_weapons[id].wmodel != __NULL__) { + if (g_weapons[id].wmodel != __NULL__) return g_weapons[id].wmodel(); - } - + return ""; } string Weapons_GetPlayermodel(int id) { - if (g_weapons[id].pmodel != __NULL__) { + if (g_weapons[id].pmodel != __NULL__) return g_weapons[id].pmodel(); - } - + return ""; } string Weapons_GetDeathmessage(int id) { - if (g_weapons[id].deathmsg != __NULL__) { + if (g_weapons[id].deathmsg != __NULL__) return g_weapons[id].deathmsg(); - } - + return ""; } -#ifdef SERVER float Weapons_GetAim(int id) { - if (g_weapons[id].aimanim != __NULL__) { + if (g_weapons[id].aimanim != __NULL__) return g_weapons[id].aimanim(); - } - - return 0; + + return (0); } -#endif #ifdef CLIENT void Weapons_HUDPic(int id, int s, vector pos, float a) { - if (g_weapons[id].hudpic != __NULL__) { + if (g_weapons[id].hudpic != __NULL__) g_weapons[id].hudpic(s, pos, a); - } } #endif @@ -250,7 +242,7 @@ vector Weapons_GetCameraPos(void) { #ifdef SERVER - return self.origin + self.view_ofs; + return (self.origin + self.view_ofs); #else return getproperty(VF_ORIGIN); #endif @@ -259,11 +251,9 @@ Weapons_GetCameraPos(void) void Weapons_ViewAnimation(int i) { -#ifdef CLIENT - player pl = (player)pSeat->m_ePlayer; - View_PlayAnimation(i); -#else player pl = (player)self; +#ifdef CLIENT + View_PlayAnimation(i); #endif pl.weapontime = 0.0f; } @@ -278,26 +268,24 @@ Weapons_GetAnimation(void) #ifdef CLIENT return View_GetAnimation(); #else - return 0; + return (0); #endif } void Weapons_ViewPunchAngle(vector add) { -#ifdef CLIENT player pl = (player)self; pl.punchangle += add; -#endif } int Weapons_IsPresent(player pl, int w) { if (pl.g_items & g_weapons[w].id) { - return TRUE; + return (1); } else { - return FALSE; + return (0); } } /* @@ -311,15 +299,12 @@ void Weapons_UpdateAmmo(base_player pl, int a1, int a2, int a3) { /* no change */ - if (a1 == -1) { + if (a1 == -1) a1 = pl.a_ammo1; - } - if (a2 == -1) { + if (a2 == -1) a2 = pl.a_ammo2; - } - if (a3 == -1) { + if (a3 == -1) a3 = pl.a_ammo3; - } /* networked as bytes, since we don't need more. Clamp to avoid errors */ pl.a_ammo1 = bound(0, a1, 255); diff --git a/src/client/entry.qc b/src/client/entry.qc index cdeec048..67f3ae4e 100644 --- a/src/client/entry.qc +++ b/src/client/entry.qc @@ -900,25 +900,8 @@ CSQC_Ent_Update(float new) pSeat = &g_seats[s]; pSeatLocal = &g_seatslocal[s]; - if (new || self.classname != "player") { - spawnfunc_player(); - pl.classname = "player"; - pl.solid = SOLID_SLIDEBOX; - pl.drawmask = MASK_ENGINE; - pl.customphysics = Empty; - setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX); - } else { - if (pl.entnum == player_localentnum) { - for (int i = pl.sequence+1; i <= servercommandframe; i++) { - /* ...maybe the input state is too old? */ - if (!getinputstate(i)) { - break; - } - input_sequence = i; - PMove_Run(); - } - } - } + + Predict_EntityUpdate(pl, new); /* any differences in things that are read below are now officially from prediction misses. */ diff --git a/src/client/predict.qc b/src/client/predict.qc index 7b17ebf7..4d6ed380 100644 --- a/src/client/predict.qc +++ b/src/client/predict.qc @@ -14,6 +14,54 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +/* +================= +Predict_EntityUpdate + +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). +================= +*/ +void +Predict_EntityUpdate(player pl, float new) +{ + /* this is a new client entity, let's set it up right */ + if (new || self.classname != "player") { + spawnfunc_player(); + pl.classname = "player"; + + if (pl.entnum == player_localentnum) { + pl.solid = SOLID_SLIDEBOX; + pl.movetype = MOVETYPE_NONE; + pl.customphysics = Empty; + } else { + /* other players will act like missiles for interpolation purposes */ + pl.solid = SOLID_SLIDEBOX; + pl.movetype = MOVETYPE_FLY; + pl.customphysics = __NULL__; + } + + pl.drawmask = MASK_ENGINE; + setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX); + return; + } + + /* this is us, so we know about this clients' input_ fields */ + if (pl.entnum == player_localentnum) { + /* run the player physics from the last approved servercommandframe to the current one */ + for (int i = pl.sequence+1; i <= servercommandframe; i++) { + /* ...maybe the input state is too old? */ + if (!getinputstate(i)) { + break; + } + input_sequence = i; + PMove_Run(); + } + } + +} + /* ================= Predict_PreFrame diff --git a/src/gs-entbase/server/basemonster.h b/src/gs-entbase/server/basemonster.h index cb95463a..ea2ab16e 100644 --- a/src/gs-entbase/server/basemonster.h +++ b/src/gs-entbase/server/basemonster.h @@ -32,7 +32,7 @@ typedef enumflags MSF_RESERVED1, MSF_PRISONER, MSF_RESERVED2, - MSF_RESERVED3, + MSF_IGNOREPLAYER, MSF_WAITFORSCRIPT, MSF_PREDISASTER, MSF_FADECORPSE, diff --git a/src/gs-entbase/server/basemonster.qc b/src/gs-entbase/server/basemonster.qc index 08c06080..0866e169 100644 --- a/src/gs-entbase/server/basemonster.qc +++ b/src/gs-entbase/server/basemonster.qc @@ -99,6 +99,9 @@ CBaseMonster::SeeThink(void) if (w.health <= 0) continue; + if ((w.flags & FL_CLIENT) && (spawnflags & MSF_IGNOREPLAYER)) + continue; + /* first, is the potential enemy in our field of view? */ makevectors(v_angle); vector v = normalize(w.origin - origin); diff --git a/src/menu-fn/entry.qc b/src/menu-fn/entry.qc index 6f3ed35f..d25f7398 100644 --- a/src/menu-fn/entry.qc +++ b/src/menu-fn/entry.qc @@ -271,7 +271,7 @@ Menu_InputEvent(float evtype, float scanx, float chary, float devid) } main_input(evtype, scanx, chary, devid); - return TRUE; + return (1); } void @@ -342,7 +342,7 @@ m_consolecommand(string cmd) argv(1))); break; default: - return FALSE; + return (0); } - return TRUE; + return (1); } diff --git a/src/menu-fn/m_customgame.qc b/src/menu-fn/m_customgame.qc index 90c826a2..d35816d2 100644 --- a/src/menu-fn/m_customgame.qc +++ b/src/menu-fn/m_customgame.qc @@ -46,7 +46,7 @@ game_getpackageid(string pkgname) } /* no package id whatsoever */ - return -1; + return (-1); } /* return 1 if any of the packages are pending, installing, or corrupt */ @@ -66,31 +66,31 @@ game_updatesavailable(void) switch (status) { case "": if (updates[id].installed == "") { - return 1; + return (1); } else if (updates[id].installed == "pending") { - return 1; + return (1); } break; case "pending": - return 1; + return (1); break; case "enabled": break; case "present": - return 1; + return (1); break; case "corrupt": - return 1; + return (1); break; default: /* we're currently installing stuff */ - return 1; + return (1); break; } } /* everything is installed */ - return 0; + return (0); } int @@ -100,7 +100,7 @@ game_updateinstallcount(void) /* always return something positive when no packages are defined */ if (games[gameinfo_current].pkgname == "") { - return 1; + return (1); } /* look for the valid packages in the gameinfo pkgname */ diff --git a/src/menu-fn/modserver.qc b/src/menu-fn/modserver.qc index efde5379..98d80db4 100644 --- a/src/menu-fn/modserver.qc +++ b/src/menu-fn/modserver.qc @@ -31,7 +31,7 @@ memrealloc(__variant *oldptr, int elementsize, int old_num, int new_num) if (!n) { print("^1memrealloc^7: Out of memory\n"); - return 0; + return (0); } memcpy(n, oldptr, elementsize * old_num); diff --git a/src/menu-fn/servers.qc b/src/menu-fn/servers.qc index 34cbe58f..c3c8c0bf 100644 --- a/src/menu-fn/servers.qc +++ b/src/menu-fn/servers.qc @@ -18,13 +18,13 @@ int Server_IsLan(string address) { #if 0 - return FALSE; + return (0); #endif tokenizebyseparator(address, "."); if (argv(0) == "192" && argv(1) == "168") { - return TRUE; + return (1); } else { - return FALSE; + return (0); } } diff --git a/src/menu-fn/tcp.qc b/src/menu-fn/tcp.qc index 6db6a812..d7832489 100644 --- a/src/menu-fn/tcp.qc +++ b/src/menu-fn/tcp.qc @@ -62,18 +62,18 @@ TCP_Send(tcpinfo_t *in, string msg) { if (in.m_iState == STATE_DISCONNECTED) { dprint("^1TCP_Send^7: Can't send, we're disconnected\n"); - return 0; + return (0); } /* the buffer is full. we've been unable to send messages for a while */ if (in.m_iBufferLines >= (TCP_BUFFER_LENGTH - 1)) { dprint("^1TCP_Send^7: Buffer full.\n"); - return 0; + return (0); } in.m_strBuffer[in.m_iBufferLines] = msg; in.m_iBufferLines++; - return 1; + return (1); } string diff --git a/src/menu-fn/util.qc b/src/menu-fn/util.qc index 2ed9b39f..d19251cd 100644 --- a/src/menu-fn/util.qc +++ b/src/menu-fn/util.qc @@ -30,11 +30,11 @@ Util_CheckMouse(int x, int y, int sx, int sy) if (g_mousepos[0] >= mins[0] && g_mousepos[0] <= maxs[0]) { if (g_mousepos[1] >= mins[1] && g_mousepos[1] <= maxs[1]) { - return TRUE; + return (1); } } - return FALSE; + return (0); } string diff --git a/src/plugins/connectsounds.qc b/src/plugins/connectsounds.qc index ab24d621..15d98922 100755 --- a/src/plugins/connectsounds.qc +++ b/src/plugins/connectsounds.qc @@ -23,7 +23,7 @@ FMX_PlayerConnect(entity cl) sound(g_cnspk, CHAN_VOICE, "sound/buttons/bell1.wav", 1.0f, ATTN_NONE); strIP = infokey(cl, INFOKEY_P_IP); bprint(PRINT_CHAT, sprintf("%s joined (%s)\n", cl.netname, strIP)); - return TRUE; + return (1); } int @@ -33,7 +33,7 @@ FMX_PlayerDisconnect(entity cl) sound(g_cnspk, CHAN_VOICE, "sound/buttons/blip1.wav", 1.0f, ATTN_NONE); strIP = infokey(cl, INFOKEY_P_IP); bprint(PRINT_CHAT, sprintf("%s left (%s)\n", cl.netname, strIP)); - return TRUE; + return (1); } void diff --git a/src/shared/player.qc b/src/shared/player.qc index 120505e7..b30d5af3 100644 --- a/src/shared/player.qc +++ b/src/shared/player.qc @@ -15,10 +15,21 @@ */ #ifdef CLIENT +/* +================= +base_player::ReceiveEntity + +Receive the generic client attributes from the server. +If you want to override this, do not call this +at the top of player::ReceiveEntity +================= +*/ void base_player::ReceiveEntity(float new, float fl) { - /* seed for our prediction table */ + /* store which input sequence we're on, this helps us + * later when we run prediction again between last/latest + * servercommandframe */ sequence = servercommandframe; /* HACK: we need to make this more reliable */ @@ -79,6 +90,15 @@ base_player::ReceiveEntity(float new, float fl) punchangle[2] = readfloat(); } +/* +================= +base_player::PredictPreFrame + +Save the state of the last server-confirmed attributes. +If you want to override this, do not call this +at the top of player::PredictPreFrame +================= +*/ void base_player::PredictPreFrame(void) { @@ -105,6 +125,16 @@ base_player::PredictPreFrame(void) SAVE_STATE(punchangle); } +/* +================= +base_player::PredictPostFrame + +After running prediction on the client, roll back the values +to the server's confirmed saved attributes from PredictPreFrame. +If you want to override this, do not call this +at the top of player::PredictPostFrame +================= +*/ void base_player::PredictPostFrame(void) { @@ -130,8 +160,16 @@ base_player::PredictPostFrame(void) ROLL_BACK(w_idle_next); ROLL_BACK(punchangle); } - #else +/* +================= +base_player::EvaluateEntity + +Check which attributes have changed and flag the ones that did. +If you want to override this, do not call this +at the top of player::EvaluateEntity +================= +*/ void base_player::EvaluateEntity(void) { @@ -213,18 +251,32 @@ base_player::EvaluateEntity(void) SAVE_STATE(punchangle); } +/* +================= +base_player::SendEntity + +Network any attributes that have been flagged for networking. +If you want to override this, do not call this +at the top of player::SendEntity +================= +*/ float base_player::SendEntity(entity ePEnt, float fChanged) { /* really trying to get our moneys worth with 23 bits of mantissa */ if (fChanged & PLAYER_MODELINDEX) WriteShort(MSG_ENTITY, modelindex); + + /* if origin[0] changes, it's very likely [1] changes too, since + * we rarely ever walk in a straight line on the world grid */ if (fChanged & PLAYER_ORIGIN) { WriteCoord(MSG_ENTITY, origin[0]); WriteCoord(MSG_ENTITY, origin[1]); } + /* the height doesn't change as much */ if (fChanged & PLAYER_ORIGIN_Z) WriteCoord(MSG_ENTITY, origin[2]); + if (fChanged & PLAYER_ANGLES_X) WriteFloat(MSG_ENTITY, v_angle[0]); if (fChanged & PLAYER_ANGLES_Y) @@ -232,11 +284,11 @@ base_player::SendEntity(entity ePEnt, float fChanged) if (fChanged & PLAYER_ANGLES_Z) WriteFloat(MSG_ENTITY, angles[2]); + /* similar as with origin, we separate x/y from z */ if (fChanged & PLAYER_VELOCITY) { WriteCoord(MSG_ENTITY, velocity[0]); WriteCoord(MSG_ENTITY, velocity[1]); } - if (fChanged & PLAYER_VELOCITY_Z) WriteCoord(MSG_ENTITY, velocity[2]); @@ -246,14 +298,21 @@ base_player::SendEntity(entity ePEnt, float fChanged) } if (fChanged & PLAYER_WEAPON) WriteByte(MSG_ENTITY, activeweapon); + + /* g_items is a proper integer, so we can't let WriteFloat truncate it (hence __variant) */ if (fChanged & PLAYER_ITEMS) WriteFloat(MSG_ENTITY, (__variant)g_items); + + /* only got byte precision, clamp to avoid weird values on the client-side */ if (fChanged & PLAYER_HEALTH) WriteByte(MSG_ENTITY, bound(0, health, 255)); if (fChanged & PLAYER_ARMOR) WriteByte(MSG_ENTITY, bound(0, armor, 255)); + if (fChanged & PLAYER_MOVETYPE) WriteByte(MSG_ENTITY, movetype); + + /* the view_ofs[0] and [1] are rarely changed */ if (fChanged & PLAYER_VIEWOFS) WriteFloat(MSG_ENTITY, view_ofs[2]);