Port most client networked cvars to ClientState
authorMario <mario@smbclan.net>
Mon, 17 Jul 2017 22:37:47 +0000 (08:37 +1000)
committerMario <mario@smbclan.net>
Mon, 17 Jul 2017 22:37:47 +0000 (08:37 +1000)
29 files changed:
qcsrc/common/effects/qc/globalsound.qc
qcsrc/common/mutators/mutator/buffs/sv_buffs.qc
qcsrc/common/mutators/mutator/dodging/sv_dodging.qc
qcsrc/common/mutators/mutator/multijump/multijump.qc
qcsrc/common/mutators/mutator/nades/nades.qc
qcsrc/common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc
qcsrc/common/physics/player.qc
qcsrc/common/physics/player.qh
qcsrc/common/playerstats.qc
qcsrc/common/state.qc
qcsrc/common/stats.qh
qcsrc/common/t_items.qc
qcsrc/common/weapons/weapon/shockwave.qc
qcsrc/lib/replicate.qh
qcsrc/server/bot/default/bot.qc
qcsrc/server/client.qc
qcsrc/server/client.qh
qcsrc/server/command/cmd.qc
qcsrc/server/defs.qh
qcsrc/server/g_subs.qc
qcsrc/server/g_world.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/mutator/gamemode_ctf.qc
qcsrc/server/mutators/mutator/gamemode_cts.qc
qcsrc/server/mutators/mutator/gamemode_race.qc
qcsrc/server/player.qc
qcsrc/server/weapons/accuracy.qc
qcsrc/server/weapons/selection.qc
qcsrc/server/weapons/tracing.qc

index d60b2e8..c3aaf62 100644 (file)
                                                msg_entity = this.pusher;
                                                if (IS_REAL_CLIENT(msg_entity))
                                                {
-                                                       float atten = (msg_entity.cvar_cl_voice_directional == 1) ? ATTEN_MIN : ATTEN_NONE;
+                                                       float atten = (CS(msg_entity).cvar_cl_voice_directional == 1) ? ATTEN_MIN : ATTEN_NONE;
                                                        if (gs) globalsound(MSG_ONE, this, gs, r, chan, vol, atten);
                                                        else if (ps) playersound(MSG_ONE, this, ps, r, chan, vol, atten);
                                                        else soundto(MSG_ONE, this, chan, sample, vol, atten);
                                        #define X() \
                                                MACRO_BEGIN \
                                                { \
-                                                       float atten = (msg_entity.cvar_cl_voice_directional == 1) ? ATTEN_MIN : ATTEN_NONE; \
+                                                       float atten = (CS(msg_entity).cvar_cl_voice_directional == 1) ? ATTEN_MIN : ATTEN_NONE; \
                                                        if (gs) globalsound(MSG_ONE, this, gs, r, chan, vol, atten); \
                                                        else if (ps) playersound(MSG_ONE, this, ps, r, chan, vol, atten); \
                                                        else soundto(MSG_ONE, this, chan, sample, vol, atten); \
                                        #define X() \
                                                MACRO_BEGIN \
                                                { \
-                                                       if (voicetype != VOICETYPE_AUTOTAUNT || tauntrand < msg_entity.cvar_cl_autotaunt) \
+                                                       if (voicetype != VOICETYPE_AUTOTAUNT || tauntrand < CS(msg_entity).cvar_cl_autotaunt) \
                                                        { \
-                                                               float atten = (msg_entity.cvar_cl_voice_directional >= 1) \
-                                                                   ? bound(ATTEN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, \
+                                                               float atten = (CS(msg_entity).cvar_cl_voice_directional >= 1) \
+                                                                   ? bound(ATTEN_MIN, CS(msg_entity).cvar_cl_voice_directional_taunt_attenuation, \
                                                                        ATTEN_MAX) \
                                                                        : ATTEN_NONE; \
                                                                if (gs) globalsound(MSG_ONE, this, gs, r, chan, vol, atten); \
index 032ecff..ffa9ce2 100644 (file)
@@ -85,7 +85,7 @@ bool buff_Waypoint_visible_for_player(entity this, entity player, entity view)
 
        if (view.buffs)
        {
-               return view.cvar_cl_buffs_autoreplace == false || view.buffs != this.owner.buffs;
+               return CS(view).cvar_cl_buffs_autoreplace == false || view.buffs != this.owner.buffs;
        }
 
        return WaypointSprite_visible_for_player(this, player, view);
@@ -177,7 +177,7 @@ void buff_Touch(entity this, entity toucher)
 
        if (toucher.buffs)
        {
-               if (toucher.cvar_cl_buffs_autoreplace && toucher.buffs != this.buffs)
+               if (CS(toucher).cvar_cl_buffs_autoreplace && toucher.buffs != this.buffs)
                {
                        int buffid = buff_FirstFromFlags(toucher.buffs).m_id;
                        //Send_Notification(NOTIF_ONE, toucher, MSG_MULTI, ITEM_BUFF_DROP, toucher.buffs);
index 93feb5d..d62aa42 100644 (file)
@@ -35,7 +35,7 @@
        #define PHYS_DODGING_PRESSED_KEYS(s)            (s).pressedkeys
 #elif defined(SVQC)
        #define PHYS_DODGING_FRAMETIME                          sys_frametime
-       #define PHYS_DODGING_TIMEOUT(s)                         s.cvar_cl_dodging_timeout
+       #define PHYS_DODGING_TIMEOUT(s)                         CS(s).cvar_cl_dodging_timeout
        #define PHYS_DODGING_PRESSED_KEYS(s)            CS(s).pressedkeys
 #endif
 
@@ -52,7 +52,7 @@ bool autocvar_sv_dodging_sound;
 #include <common/animdecide.qh>
 #include <common/physics/player.qh>
 
-.float cvar_cl_dodging_timeout = _STAT(DODGING_TIMEOUT);
+.float cvar_cl_dodging_timeout;
 
 REGISTER_MUTATOR(dodging, cvar("g_dodging"))
 {
@@ -307,6 +307,13 @@ MUTATOR_HOOKFUNCTION(dodging, PlayerPhysics)
 
 REPLICATE(cvar_cl_dodging_timeout, float, "cl_dodging_timeout");
 
+MUTATOR_HOOKFUNCTION(dodging, PlayerPreThink)
+{
+       entity player = M_ARGV(0, entity);
+
+       STAT(DODGING_TIMEOUT, player) = CS(player).cvar_cl_dodging_timeout;
+}
+
 MUTATOR_HOOKFUNCTION(dodging, GetPressedKeys)
 {
        entity player = M_ARGV(0, entity);
index b00ad74..47dcfd4 100644 (file)
@@ -30,7 +30,7 @@ bool autocvar_cl_multijump = true;
 #elif defined(SVQC)
 .bool cvar_cl_multijump;
 
-       #define PHYS_MULTIJUMP_CLIENT(s)        (s).cvar_cl_multijump
+       #define PHYS_MULTIJUMP_CLIENT(s)        CS(s).cvar_cl_multijump
 #endif
 
 MUTATOR_HOOKFUNCTION(multijump, PlayerPhysics)
index 9447ba3..4626610 100644 (file)
@@ -1093,8 +1093,8 @@ void nade_prime(entity this)
        }
        else
        {
-               ntype = ((autocvar_g_nades_client_select) ? this.cvar_cl_nade_type : autocvar_g_nades_nade_type);
-               pntype = ((autocvar_g_nades_client_select) ? this.cvar_cl_pokenade_type : autocvar_g_nades_pokenade_monster_type);
+               ntype = ((autocvar_g_nades_client_select) ? CS(this).cvar_cl_nade_type : autocvar_g_nades_nade_type);
+               pntype = ((autocvar_g_nades_client_select) ? CS(this).cvar_cl_pokenade_type : autocvar_g_nades_pokenade_monster_type);
        }
 
        spawn_held_nade(this, this, autocvar_g_nades_nade_lifetime, ntype, pntype);
@@ -1250,8 +1250,8 @@ MUTATOR_HOOKFUNCTION(nades, PlayerPreThink)
 
                        if(autocvar_g_nades_bonus_client_select)
                        {
-                               player.nade_type = player.cvar_cl_nade_type;
-                               player.pokenade_type = player.cvar_cl_pokenade_type;
+                               player.nade_type = CS(player).cvar_cl_nade_type;
+                               player.pokenade_type = CS(player).cvar_cl_pokenade_type;
                        }
                        else
                        {
@@ -1345,7 +1345,7 @@ MUTATOR_HOOKFUNCTION(nades, PlayerSpawn)
                player.nade_refire  = time + autocvar_g_nades_nade_refire;
 
        if(autocvar_g_nades_bonus_client_select)
-               player.nade_type = player.cvar_cl_nade_type;
+               player.nade_type = CS(player).cvar_cl_nade_type;
 
        player.nade_timer = 0;
 
index ee75728..5bfddfa 100644 (file)
@@ -24,7 +24,7 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, Spawn_Score)
        entity spawn_spot = M_ARGV(1, entity);
        vector spawn_score = M_ARGV(2, vector);
 
-       if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && player.cvar_cl_spawn_near_teammate))
+       if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && CS(player).cvar_cl_spawn_near_teammate))
                return;
 
        spawn_spot.msnt_lookat = NULL;
@@ -76,7 +76,7 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn)
                return; // at least 1 team has only 1 player, let's not give the bigger team too much of an advantage!
 
        // Note: when entering this, fixangle is already set.
-       if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && player.cvar_cl_spawn_near_teammate))
+       if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && CS(player).cvar_cl_spawn_near_teammate))
        {
                if(autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death)
                        player.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
index ec255c8..6f83e76 100644 (file)
@@ -15,9 +15,9 @@ bool Physics_Valid(string thecvar)
 
 float Physics_ClientOption(entity this, string option, float defaultval)
 {
-       if(IS_REAL_CLIENT(this) && Physics_Valid(this.cvar_cl_physics))
+       if(IS_REAL_CLIENT(this) && Physics_Valid(CS(this).cvar_cl_physics))
        {
-               string s = strcat("g_physics_", this.cvar_cl_physics, "_", option);
+               string s = strcat("g_physics_", CS(this).cvar_cl_physics, "_", option);
                if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
                        return cvar(s);
        }
@@ -433,7 +433,7 @@ void CheckWaterJump(entity this)
 
 
 #ifdef SVQC
-       #define JETPACK_JUMP(s) s.cvar_cl_jetpack_jump
+       #define JETPACK_JUMP(s) CS(s).cvar_cl_jetpack_jump
 #elif defined(CSQC)
        float autocvar_cl_jetpack_jump;
        #define JETPACK_JUMP(s) autocvar_cl_jetpack_jump
index 23456eb..7e0d397 100644 (file)
@@ -295,7 +295,7 @@ STATIC_INIT(PHYS_INPUT_BUTTON_DODGE)
        #define PHYS_JUMPSPEEDCAP_MIN               autocvar_sv_jumpspeedcap_min
        #define PHYS_JUMPSPEEDCAP_MAX               autocvar_sv_jumpspeedcap_max
 
-       #define PHYS_CL_TRACK_CANJUMP(s)            ((s).cvar_cl_movement_track_canjump)
+       #define PHYS_CL_TRACK_CANJUMP(s)            (CS(s).cvar_cl_movement_track_canjump)
 
 #endif
 
index 913e463..acc4100 100644 (file)
@@ -24,7 +24,7 @@ void PlayerStats_GameReport_AddPlayer(entity e)
        // set up player identification
        string s = "";
 
-       if((e.crypto_idfp != "") && (e.cvar_cl_allow_uidtracking == 1))
+       if((e.crypto_idfp != "") && (CS(e).cvar_cl_allow_uidtracking == 1))
                { s = e.crypto_idfp; }
        else if(IS_BOT_CLIENT(e))
                { s = sprintf("bot#%g#%s", skill, e.cleanname); }
@@ -132,7 +132,7 @@ void PlayerStats_GameReport_FinalizePlayer(entity p)
 
        db_put(PS_GR_OUT_DB, sprintf("%s:_playerid", p.playerstats_id), ftos(p.playerid));
 
-       if(p.cvar_cl_allow_uid2name == 1 || IS_BOT_CLIENT(p))
+       if(CS(p).cvar_cl_allow_uid2name == 1 || IS_BOT_CLIENT(p))
                db_put(PS_GR_OUT_DB, sprintf("%s:_netname", p.playerstats_id), playername(p, false));
 
        if(teamplay)
index a471884..730b1fa 100644 (file)
@@ -69,10 +69,10 @@ void PlayerScore_Detach(entity this);
 
 void ClientState_detach(entity this)
 {
+    GetCvars(this, -1);  // free cvars TODO: is this still needed now that it's stored on the clientstate entity?
        delete(CS(this));
        this._cs = NULL;
 
-    GetCvars(this, -1);  // free cvars
 
     bot_clientdisconnect(this);
 
index bfed439..be839b8 100644 (file)
@@ -350,7 +350,7 @@ noref int autocvar_cl_gunalign;
 .int cvar_cl_gunalign;
 REPLICATE(cvar_cl_gunalign, int, "cl_gunalign");
 #endif
-REGISTER_STAT(GUNALIGN, int, this.cvar_cl_gunalign)
+REGISTER_STAT(GUNALIGN, int)
 #ifdef SVQC
 SPECTATE_COPYFIELD(_STAT(GUNALIGN))
 #endif
index d85cf78..265fc9c 100644 (file)
@@ -695,7 +695,7 @@ float Item_GiveTo(entity item, entity player)
        // if the player is using their best weapon before items are given, they
        // probably want to switch to an even better weapon after items are given
 
-       if(player.autoswitch)
+       if(CS(player).autoswitch)
        {
                for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
@@ -1723,7 +1723,7 @@ float GiveItems(entity e, float beginarg, float endarg)
 
        int _switchweapon = 0;
 
-       if(e.autoswitch)
+       if(CS(e).autoswitch)
        {
                for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
index 8d627ad..1fa0adc 100644 (file)
@@ -399,9 +399,10 @@ void W_Shockwave_Attack(entity actor, .entity weaponentity)
        );
 
        float lag = ((IS_REAL_CLIENT(actor)) ? ANTILAG_LATENCY(actor) : 0);
+       bool noantilag = ((IS_CLIENT(actor)) ? CS(actor).cvar_cl_noantilag : false);
        if(lag < 0.001)
                lag = 0;
-       if(autocvar_g_antilag == 0 || actor.cvar_cl_noantilag)
+       if(autocvar_g_antilag == 0 || noantilag)
                lag = 0; // only do hitscan, but no antilag
        if(lag)
        {
index a36466d..c7a4204 100644 (file)
@@ -12,7 +12,7 @@
        #define REPLICATE(...) EVAL_REPLICATE(OVERLOAD(REPLICATE, __VA_ARGS__))
        #define EVAL_REPLICATE(...) __VA_ARGS__
 
-       [[accumulate]] void ReplicateVars(entity this, string thisname, int i) {}
+       [[accumulate]] void ReplicateVars(entity this, entity store, string thisname, int i) {}
 
        #define REPLICATE_3(fld, type, var) REPLICATE_4(fld, type, var, )
        #define REPLICATE_4(fld, type, var, func) REPLICATE_##type(fld, var, func)
@@ -35,9 +35,9 @@
 
        #if defined(SVQC)
                #define REPLICATE_7(fld, type, var, func, create, destroy, after) \
-                       void ReplicateVars(entity this, string thisname, int i) \
+                       void ReplicateVars(entity this, entity store, string thisname, int i) \
                        { \
-                               type field = this.fld; \
+                               type field = store.fld; \
                                if (i < 0) { destroy } \
                                else \
                                { \
@@ -53,7 +53,7 @@
                                        } \
                                        if (current) { after } \
                                } \
-                               this.fld = field; \
+                               store.fld = field; \
                        }
        #elif defined(CSQC)
                // TODO
index a1d7b10..b0814d7 100644 (file)
 #include <lib/warpzone/common.qh>
 #include <lib/warpzone/util_server.qh>
 
+// TODO: remove this function! its only purpose is to update these fields since bot_setnameandstuff is called before ClientState
+void bot_setclientfields(entity this)
+{
+       CS(this).cvar_cl_accuracy_data_share = 1;  // share the bots weapon accuracy data with the world
+       CS(this).cvar_cl_accuracy_data_receive = 0;  // don't receive any weapon accuracy data
+}
+
 entity bot_spawn()
 {
        entity bot = spawnclient();
@@ -49,6 +56,7 @@ entity bot_spawn()
                setItemGroupCount();
                currentbots = currentbots + 1;
                bot_setnameandstuff(bot);
+               bot_setclientfields(bot);
                ClientConnect(bot);
                PutClientInServer(bot);
        }
@@ -264,9 +272,6 @@ void bot_setnameandstuff(entity this)
                bot_model = strcat(bot_model, ".iqm");
        this.playermodel = this.playermodel_freeme = strzone(strcat("models/player/", bot_model));
        this.playerskin = this.playerskin_freeme = strzone(bot_skin);
-
-       this.cvar_cl_accuracy_data_share = 1;  // share the bots weapon accuracy data with the NULL
-       this.cvar_cl_accuracy_data_receive = 0;  // don't receive any weapon accuracy data
 }
 
 void bot_custom_weapon_priority_setup()
@@ -419,7 +424,10 @@ void bot_clientconnect(entity this)
        this.createdtime = this.bot_nextthink;
 
        if(!this.bot_config_loaded) // This is needed so team overrider doesn't break between matches
+       {
                bot_setnameandstuff(this);
+               bot_setclientfields(this);
+       }
 
        if(this.bot_forced_team==1)
                this.team = NUM_TEAM_1;
index bfb8849..dc09fa1 100644 (file)
@@ -2308,7 +2308,7 @@ void ObserverThink(entity this)
                                TRANSMUTE(Spectator, this);
                        }
                } else {
-                       int preferred_movetype = ((!PHYS_INPUT_BUTTON_USE(this) ? this.cvar_cl_clippedspectating : !this.cvar_cl_clippedspectating) ? MOVETYPE_FLY_WORLDONLY : MOVETYPE_NOCLIP);
+                       int preferred_movetype = ((!PHYS_INPUT_BUTTON_USE(this) ? CS(this).cvar_cl_clippedspectating : !CS(this).cvar_cl_clippedspectating) ? MOVETYPE_FLY_WORLDONLY : MOVETYPE_NOCLIP);
                        set_movetype(this, preferred_movetype);
                }
        } else {
@@ -2446,6 +2446,9 @@ Called every frame for each client before the physics are run
 .float last_vehiclecheck;
 void PlayerPreThink (entity this)
 {
+       STAT(GUNALIGN, this) = CS(this).cvar_cl_gunalign; // TODO
+       STAT(MOVEVARS_CL_TRACK_CANJUMP, this) = CS(this).cvar_cl_movement_track_canjump;
+
        WarpZone_PlayerPhysics_FixVAngle(this);
 
        if (frametime) {
@@ -2475,19 +2478,19 @@ void PlayerPreThink (entity this)
        }
 
        // version nagging
-       if (CS(this).version_nagtime && this.cvar_g_xonoticversion && time > CS(this).version_nagtime) {
+       if (CS(this).version_nagtime && CS(this).cvar_g_xonoticversion && time > CS(this).version_nagtime) {
         CS(this).version_nagtime = 0;
-        if (strstrofs(this.cvar_g_xonoticversion, "git", 0) >= 0 || strstrofs(this.cvar_g_xonoticversion, "autobuild", 0) >= 0) {
+        if (strstrofs(CS(this).cvar_g_xonoticversion, "git", 0) >= 0 || strstrofs(CS(this).cvar_g_xonoticversion, "autobuild", 0) >= 0) {
             // git client
         } else if (strstrofs(autocvar_g_xonoticversion, "git", 0) >= 0 || strstrofs(autocvar_g_xonoticversion, "autobuild", 0) >= 0) {
             // git server
-            Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_VERSION_BETA, autocvar_g_xonoticversion, this.cvar_g_xonoticversion);
+            Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_VERSION_BETA, autocvar_g_xonoticversion, CS(this).cvar_g_xonoticversion);
         } else {
-            int r = vercmp(this.cvar_g_xonoticversion, autocvar_g_xonoticversion);
+            int r = vercmp(CS(this).cvar_g_xonoticversion, autocvar_g_xonoticversion);
             if (r < 0) { // old client
-                Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_VERSION_OUTDATED, autocvar_g_xonoticversion, this.cvar_g_xonoticversion);
+                Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_VERSION_OUTDATED, autocvar_g_xonoticversion, CS(this).cvar_g_xonoticversion);
             } else if (r > 0) { // old server
-                Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_VERSION_OLD, autocvar_g_xonoticversion, this.cvar_g_xonoticversion);
+                Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_VERSION_OLD, autocvar_g_xonoticversion, CS(this).cvar_g_xonoticversion);
             }
         }
     }
@@ -2551,7 +2554,7 @@ void PlayerPreThink (entity this)
                this.last_vehiclecheck = time + 1;
        }
 
-       if(!this.cvar_cl_newusekeysupported) // FIXME remove this - it was a stupid idea to begin with, we can JUST use the button
+       if(!CS(this).cvar_cl_newusekeysupported) // FIXME remove this - it was a stupid idea to begin with, we can JUST use the button
        {
                if(PHYS_INPUT_BUTTON_USE(this) && !CS(this).usekeypressed)
                        PlayerUseKey(this);
index f0c7a3b..b4c8afa 100644 (file)
@@ -101,6 +101,36 @@ CLASS(Client, Object)
     ATTRIB(Client, latency_time, float, this.latency_time);
     ATTRIB(Client, v_angle_old, vector, this.v_angle_old);
     ATTRIB(Client, model_randomizer, float, this.model_randomizer);
+    ATTRIB(Client, cmd_floodcount, int, this.cmd_floodcount);
+    ATTRIB(Client, cmd_floodtime, float, this.cmd_floodtime);
+
+    // networked cvars
+
+    ATTRIB(Client, cvar_cl_allow_uid2name, int, this.cvar_cl_allow_uid2name);
+    ATTRIB(Client, cvar_cl_allow_uidtracking, int, this.cvar_cl_allow_uidtracking);
+    ATTRIB(Client, cvar_cl_autotaunt, float, this.cvar_cl_autotaunt);
+    ATTRIB(Client, cvar_cl_voice_directional, int, this.cvar_cl_voice_directional);
+    ATTRIB(Client, cvar_cl_voice_directional_taunt_attenuation, float, this.cvar_cl_voice_directional_taunt_attenuation);
+    ATTRIB(Client, cvar_cl_physics, string, this.cvar_cl_physics);
+    ATTRIB(Client, cvar_cl_buffs_autoreplace, bool, this.cvar_cl_buffs_autoreplace);
+    ATTRIB(Client, cvar_cl_nade_type, int, this.cvar_cl_nade_type);
+    ATTRIB(Client, cvar_cl_pokenade_type, string, this.cvar_cl_pokenade_type);
+    ATTRIB(Client, cvar_cl_spawn_near_teammate, bool, this.cvar_cl_spawn_near_teammate);
+    ATTRIB(Client, cvar_cl_gunalign, int, this.cvar_cl_gunalign);
+    ATTRIB(Client, cvar_cl_handicap, float, this.cvar_cl_handicap);
+    ATTRIB(Client, cvar_cl_clippedspectating, bool, this.cvar_cl_clippedspectating);
+    ATTRIB(Client, cvar_cl_autoscreenshot, int, this.cvar_cl_autoscreenshot);
+    ATTRIB(Client, cvar_cl_jetpack_jump, bool, this.cvar_cl_jetpack_jump);
+    ATTRIB(Client, cvar_cl_newusekeysupported, bool, this.cvar_cl_newusekeysupported);
+    ATTRIB(Client, cvar_cl_noantilag, bool, this.cvar_cl_noantilag);
+    ATTRIB(Client, cvar_cl_movement_track_canjump, bool, this.cvar_cl_movement_track_canjump);
+    ATTRIB(Client, cvar_cl_weaponimpulsemode, int, this.cvar_cl_weaponimpulsemode);
+    ATTRIB(Client, cvar_g_xonoticversion, string, this.cvar_g_xonoticversion);
+    ATTRIB(Client, autoswitch, bool, this.autoswitch);
+    ATTRIB(Client, cvar_cl_dodging_timeout, float, this.cvar_cl_dodging_timeout);
+    ATTRIB(Client, cvar_cl_multijump, bool, this.cvar_cl_multijump);
+    ATTRIB(Client, cvar_cl_accuracy_data_share, bool, this.cvar_cl_accuracy_data_share);
+    ATTRIB(Client, cvar_cl_accuracy_data_receive, bool, this.cvar_cl_accuracy_data_receive);
 
     METHOD(Client, m_unwind, bool(Client this));
 
index 6d7ee81..542d196 100644 (file)
@@ -45,17 +45,19 @@ void ClientKill_TeamChange(entity this, float targetteam);  // 0 = don't change,
 
 bool SV_ParseClientCommand_floodcheck(entity this)
 {
+       entity store = IS_CLIENT(this) ? CS(this) : this; // unfortunately, we need to store these on the client initially
+
        if (!timeout_status)  // not while paused
        {
-               if (time <= (this.cmd_floodtime + autocvar_sv_clientcommand_antispam_time))
+               if (time <= (store.cmd_floodtime + autocvar_sv_clientcommand_antispam_time))
                {
-                       this.cmd_floodcount += 1;
-                       if (this.cmd_floodcount > autocvar_sv_clientcommand_antispam_count)   return false;  // too much spam, halt
+                       store.cmd_floodcount += 1;
+                       if (store.cmd_floodcount > autocvar_sv_clientcommand_antispam_count)   return false;  // too much spam, halt
                }
                else
                {
-                       this.cmd_floodtime = time;
-                       this.cmd_floodcount = 1;
+                       store.cmd_floodtime = time;
+                       store.cmd_floodcount = 1;
                }
        }
        return true;  // continue, as we're not flooding yet
@@ -74,8 +76,8 @@ void ClientCommand_autoswitch(entity caller, float request, float argc)
                {
                        if (argv(1) != "")
                        {
-                               caller.autoswitch = InterpretBoolean(argv(1));
-                               sprint(caller, strcat("^1autoswitch is currently turned ", (caller.autoswitch ? "on" : "off"), ".\n"));
+                               CS(caller).autoswitch = InterpretBoolean(argv(1));
+                               sprint(caller, strcat("^1autoswitch is currently turned ", (CS(caller).autoswitch ? "on" : "off"), ".\n"));
                                return;
                        }
                }
@@ -214,7 +216,7 @@ void ClientCommand_physics(entity caller, float request, float argc)
                }
 
                default:
-                       sprint(caller, strcat("Current physics set: ^3", caller.cvar_cl_physics, "\n"));
+                       sprint(caller, strcat("Current physics set: ^3", CS(caller).cvar_cl_physics, "\n"));
                case CMD_REQUEST_USAGE:
                {
                        sprint(caller, "\nUsage:^3 cmd physics <physics>\n");
index a18e54d..0aa1424 100644 (file)
@@ -162,7 +162,7 @@ float default_weapon_alpha;
 .float cvar_cl_clippedspectating;
 .float cvar_cl_autoscreenshot;
 .float cvar_cl_jetpack_jump;
-.float cvar_cl_movement_track_canjump = _STAT(MOVEVARS_CL_TRACK_CANJUMP);
+.float cvar_cl_movement_track_canjump;
 .float cvar_cl_newusekeysupported;
 
 .string cvar_g_xonoticversion;
index 33f471e..68421f4 100644 (file)
@@ -83,13 +83,15 @@ void traceline_antilag_force (entity source, vector v1, vector v2, float nomonst
 }
 void traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
 {
-       if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
+       bool noantilag = ((IS_CLIENT(source)) ? CS(source).cvar_cl_noantilag : false);
+       if (autocvar_g_antilag != 2 || noantilag)
                lag = 0;
        traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
 }
 void tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
 {
-       if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
+       bool noantilag = ((IS_CLIENT(source)) ? CS(source).cvar_cl_noantilag : false);
+       if (autocvar_g_antilag != 2 || noantilag)
                lag = 0;
        tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, false);
 }
@@ -99,13 +101,15 @@ void WarpZone_traceline_antilag_force (entity source, vector v1, vector v2, floa
 }
 void WarpZone_traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
 {
-       if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
+       bool noantilag = ((IS_CLIENT(source)) ? CS(source).cvar_cl_noantilag : false);
+       if (autocvar_g_antilag != 2 || noantilag)
                lag = 0;
        WarpZone_traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
 }
 void WarpZone_tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
 {
-       if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
+       bool noantilag = ((IS_CLIENT(source)) ? CS(source).cvar_cl_noantilag : false);
+       if (autocvar_g_antilag != 2 || noantilag)
                lag = 0;
        tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, true);
 }
index 73a5b8a..ea78ea2 100644 (file)
@@ -1328,8 +1328,8 @@ void IntermissionThink(entity this)
 {
        FixIntermissionClient(this);
 
-       float server_screenshot = (autocvar_sv_autoscreenshot && this.cvar_cl_autoscreenshot);
-       float client_screenshot = (this.cvar_cl_autoscreenshot == 2);
+       float server_screenshot = (autocvar_sv_autoscreenshot && CS(this).cvar_cl_autoscreenshot);
+       float client_screenshot = (CS(this).cvar_cl_autoscreenshot == 2);
 
        if( (server_screenshot || client_screenshot)
                && ((this.autoscreenshot > 0) && (time > this.autoscreenshot)) )
index a1e8530..31dc225 100644 (file)
@@ -420,7 +420,7 @@ void GetCvars(entity this, int f)
 
        Notification_GetCvars(this);
 
-       ReplicateVars(this, s, f);
+       ReplicateVars(this, CS(this), s, f);
 
        GetCvars_handleString_Fixup(this, s, f, cvar_cl_weaponpriority, "cl_weaponpriority", W_FixWeaponOrder_ForceComplete_AndBuildImpulseList);
        GetCvars_handleString_Fixup(this, s, f, cvar_cl_weaponpriorities[0], "cl_weaponpriority0", W_FixWeaponOrder_AllowIncomplete);
@@ -434,7 +434,7 @@ void GetCvars(entity this, int f)
        GetCvars_handleString_Fixup(this, s, f, cvar_cl_weaponpriorities[8], "cl_weaponpriority8", W_FixWeaponOrder_AllowIncomplete);
        GetCvars_handleString_Fixup(this, s, f, cvar_cl_weaponpriorities[9], "cl_weaponpriority9", W_FixWeaponOrder_AllowIncomplete);
 
-       GetCvars_handleFloat(this, this, s, f, cvar_cl_allow_uidtracking, "cl_allow_uidtracking");
+       GetCvars_handleFloat(this, CS(this), s, f, cvar_cl_allow_uidtracking, "cl_allow_uidtracking");
 
        // fixup of switchweapon (needed for LMS or when spectating is disabled, as PutClientInServer comes too early)
        if (f > 0)
index 253a07e..ff5c28f 100644 (file)
@@ -2237,7 +2237,7 @@ MUTATOR_HOOKFUNCTION(ctf, GetPressedKeys)
 
        entity player = M_ARGV(0, entity);
 
-       if(player.cvar_cl_allow_uidtracking == 1 && player.cvar_cl_allow_uid2name == 1)
+       if(CS(player).cvar_cl_allow_uidtracking == 1 && CS(player).cvar_cl_allow_uid2name == 1)
        {
                if (!player.stored_netname)
                        player.stored_netname = strzone(uid2name(player.crypto_idfp));
index 8e7512e..f12d5f7 100644 (file)
@@ -267,7 +267,7 @@ MUTATOR_HOOKFUNCTION(cts, GetPressedKeys)
 {
        entity player = M_ARGV(0, entity);
 
-       if(player.cvar_cl_allow_uidtracking == 1 && player.cvar_cl_allow_uid2name == 1)
+       if(CS(player).cvar_cl_allow_uidtracking == 1 && CS(player).cvar_cl_allow_uid2name == 1)
        {
                if (!player.stored_netname)
                        player.stored_netname = strzone(uid2name(player.crypto_idfp));
index b1759fb..496d85e 100644 (file)
@@ -312,7 +312,7 @@ MUTATOR_HOOKFUNCTION(rc, GetPressedKeys)
 {
        entity player = M_ARGV(0, entity);
 
-       if(player.cvar_cl_allow_uidtracking == 1 && player.cvar_cl_allow_uid2name == 1)
+       if(CS(player).cvar_cl_allow_uidtracking == 1 && CS(player).cvar_cl_allow_uid2name == 1)
        {
                if (!player.stored_netname)
                        player.stored_netname = strzone(uid2name(player.crypto_idfp));
index e34826c..947fd6d 100644 (file)
@@ -317,9 +317,9 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
 
        if(!DEATH_ISSPECIAL(deathtype))
        {
-               damage *= bound(1.0, this.cvar_cl_handicap, 10.0);
-               if(this != attacker)
-                       damage /= bound(1.0, attacker.cvar_cl_handicap, 10.0);
+               damage *= bound(1.0, CS(this).cvar_cl_handicap, 10.0);
+               if(this != attacker && IS_PLAYER(attacker))
+                       damage /= bound(1.0, CS(attacker).cvar_cl_handicap, 10.0);
        }
 
        if (time < this.spawnshieldtime && autocvar_g_spawnshield_blockdamage < 1)
index 7cc06da..169d24e 100644 (file)
@@ -23,7 +23,7 @@ bool accuracy_send(entity this, entity to, int sf)
        a = a.accuracy;
 
        if (to != a.owner)
-               if (!autocvar_sv_accuracy_data_share && !a.owner.cvar_cl_accuracy_data_share)
+               if (!autocvar_sv_accuracy_data_share && !CS(a.owner).cvar_cl_accuracy_data_share)
                        sf = 0;
        // note: zero sendflags can never be sent... so we can use that to say that we send no accuracy!
        WriteInt24_t(MSG_ENTITY, sf);
index 17ba0dc..15983bd 100644 (file)
@@ -290,7 +290,7 @@ void W_CycleWeapon(entity this, string weaponorder, float dir, .entity weaponent
 void W_NextWeaponOnImpulse(entity this, float imp, .entity weaponentity)
 {
        float w;
-       w = W_GetCycleWeapon(this, this.cvar_cl_weaponpriority, +1, imp, 1, (this.cvar_cl_weaponimpulsemode == 0), weaponentity);
+       w = W_GetCycleWeapon(this, this.cvar_cl_weaponpriority, +1, imp, 1, (CS(this).cvar_cl_weaponimpulsemode == 0), weaponentity);
        if(w > 0)
                W_SwitchWeapon(this, Weapons_from(w), weaponentity);
 }
index 4c6304a..bfa7a2d 100644 (file)
@@ -84,7 +84,7 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vect
        //vector prevend = w_shotend;
 
        if (antilag)
-       if (!ent.cvar_cl_noantilag)
+       if (!CS(ent).cvar_cl_noantilag)
        {
                if (autocvar_g_antilag == 1) // switch to "ghost" if not hitting original
                {
@@ -351,7 +351,8 @@ void fireBullet(entity this, .entity weaponentity, vector start, vector dir, flo
        float lag = ((IS_REAL_CLIENT(this)) ? ANTILAG_LATENCY(this) : 0);
        if(lag < 0.001)
                lag = 0;
-       if(autocvar_g_antilag == 0 || this.cvar_cl_noantilag)
+       bool noantilag = ((IS_CLIENT(this)) ? CS(this).cvar_cl_noantilag : false);
+       if(autocvar_g_antilag == 0 || noantilag)
                lag = 0; // only do hitscan, but no antilag
        if(lag)
        {