]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/client.qc
Merge branch 'master' into Mario/overkill
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / client.qc
index 04c35a11761ffbb05b04cec53c55919c53b4a55c..eaa55cef54cc8eb5b0bd56130935473f650f0f2d 100644 (file)
@@ -23,6 +23,7 @@
 #include "bot/api.qh"
 
 #include "../common/ent_cs.qh"
+#include "../common/wepent.qh"
 #include <common/state.qh>
 
 #include <common/effects/qc/globalsound.qh>
@@ -112,7 +113,6 @@ bool ClientData_Send(entity this, entity to, int sf)
        if (e.race_completed)       sf |= 1; // forced scoreboard
        if (to.spectatee_status)    sf |= 2; // spectator ent number follows
        if (e.zoomstate)            sf |= 4; // zoomed
-       if (e.porto_v_angle_held)   sf |= 8; // angles held
        if (autocvar_sv_showspectators) sf |= 16; // show spectators
 
        WriteHeader(MSG_ENTITY, ENT_CLIENT_CLIENTDATA);
@@ -122,11 +122,6 @@ bool ClientData_Send(entity this, entity to, int sf)
        {
                WriteByte(MSG_ENTITY, to.spectatee_status);
        }
-       if (sf & 8)
-       {
-               WriteAngle(MSG_ENTITY, e.v_angle.x);
-               WriteAngle(MSG_ENTITY, e.v_angle.y);
-       }
 
        if(sf & 16)
        {
@@ -236,7 +231,7 @@ void PutObserverInServer(entity this)
         this.angles_z = 0;
         this.fixangle = true;
         // offset it so that the spectator spawns higher off the ground, looks better this way
-        setorigin(this, spot.origin + STAT(PL_VIEW_OFS, NULL));
+        setorigin(this, spot.origin + STAT(PL_VIEW_OFS, this));
         this.prevorigin = this.origin;
         if (IS_REAL_CLIENT(this))
         {
@@ -253,11 +248,11 @@ void PutObserverInServer(entity this)
                FixPlayermodel(this);
         }
         setmodel(this, MDL_Null);
-        setsize(this, STAT(PL_CROUCH_MIN, NULL), STAT(PL_CROUCH_MAX, NULL));
+        setsize(this, STAT(PL_CROUCH_MIN, this), STAT(PL_CROUCH_MAX, this));
         this.view_ofs = '0 0 0';
     }
 
-    RemoveGrapplingHook(this);
+    RemoveGrapplingHooks(this);
        Portal_ClearAll(this);
        Unfreeze(this);
        SetSpectatee(this, NULL);
@@ -284,8 +279,8 @@ void PutObserverInServer(entity this)
        if (this.killcount != FRAGS_SPECTATOR)
        {
                Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_SPECTATE, this.netname);
-               if(!intermission_running)
-               if(autocvar_g_chat_nospectators == 1 || (!(warmup_stage || gameover) && autocvar_g_chat_nospectators == 2))
+               if(!game_stopped)
+               if(autocvar_g_chat_nospectators == 1 || (!warmup_stage && autocvar_g_chat_nospectators == 2))
                        Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_CHAT_NOSPECTATORS);
 
                if(this.just_joined == false) {
@@ -336,7 +331,6 @@ void PutObserverInServer(entity this)
        this.istypefrag = 0;
        setthink(this, func_null);
        this.nextthink = 0;
-       this.hook_time = 0;
        this.deadflag = DEAD_NO;
        this.crouch = false;
        this.revive_progress = 0;
@@ -346,7 +340,6 @@ void PutObserverInServer(entity this)
        this.weapons = '0 0 0';
        this.drawonlytoclient = this;
 
-       this.weaponname = "";
        this.weaponmodel = "";
        for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
@@ -361,10 +354,6 @@ void PutObserverInServer(entity this)
        this.oldvelocity = this.velocity;
        this.fire_endtime = -1;
        this.event_damage = func_null;
-
-       STAT(ACTIVEWEAPON, this) = WEP_Null.m_id;
-       STAT(SWITCHINGWEAPON, this) = WEP_Null.m_id;
-       STAT(SWITCHWEAPON, this) = WEP_Null.m_id;
 }
 
 int player_getspecies(entity this)
@@ -495,9 +484,8 @@ void PutClientInServer(entity this)
                WriteByte(MSG_ONE, SVC_SETVIEW);
                WriteEntity(MSG_ONE, this);
        }
-       if (gameover) {
+       if (game_stopped)
                TRANSMUTE(Observer, this);
-       }
 
        SetSpectatee(this, NULL);
 
@@ -664,7 +652,8 @@ void PutClientInServer(entity this)
 
                for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
-                       CL_SpawnWeaponentity(this, weaponentities[slot]);
+                       .entity weaponentity = weaponentities[slot];
+                       CL_SpawnWeaponentity(this, weaponentity);
                }
                this.alpha = default_player_alpha;
                this.colormod = '1 1 1' * autocvar_g_player_brightness;
@@ -679,7 +668,11 @@ void PutClientInServer(entity this)
                        it.wr_resetplayer(it, this);
                        // reload all reloadable weapons
                        if (it.spawnflags & WEP_FLAG_RELOADABLE) {
-                               this.weapon_load[it.m_id] = it.reloading_ammo;
+                               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                               {
+                                       .entity weaponentity = weaponentities[slot];
+                                       this.(weaponentity).weapon_load[it.m_id] = it.reloading_ammo;
+                               }
                        }
                ));
 
@@ -700,11 +693,20 @@ void PutClientInServer(entity this)
                        delete(spot); // usefull for checking if there are spawnpoints, that let drop through the floor
                }
 
-               PS(this).m_switchweapon = w_getbestweapon(this);
-               this.cnt = -1; // W_LastWeapon will not complain
-               PS(this).m_weapon = WEP_Null;
-               this.weaponname = "";
-               PS(this).m_switchingweapon = WEP_Null;
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(slot == 0)
+                               this.(weaponentity).m_switchweapon = w_getbestweapon(this, weaponentity);
+                       else
+                               this.(weaponentity).m_switchweapon = WEP_Null;
+                       this.(weaponentity).m_weapon = WEP_Null;
+                       this.(weaponentity).weaponname = "";
+                       this.(weaponentity).m_switchingweapon = WEP_Null;
+                       this.(weaponentity).cnt = -1;
+               }
+
+               MUTATOR_CALLHOOK(PlayerWeaponSelect, this);
 
                if (!warmup_stage && !this.alivetime)
                        this.alivetime = time;
@@ -868,7 +870,7 @@ void ClientKill_Now(entity this)
 }
 void KillIndicator_Think(entity this)
 {
-       if (gameover)
+       if (game_stopped)
        {
                this.owner.killindicator = NULL;
                delete(this);
@@ -912,7 +914,7 @@ void ClientKill_TeamChange (entity this, float targetteam) // 0 = don't change,
        float killtime;
        float starttime;
 
-       if (gameover)
+       if (game_stopped)
                return;
 
        killtime = autocvar_g_balance_kill_delay;
@@ -1004,7 +1006,7 @@ void ClientKill_TeamChange (entity this, float targetteam) // 0 = don't change,
 
 void ClientKill (entity this)
 {
-       if(gameover) return;
+       if(game_stopped) return;
        if(this.player_blocked) return;
        if(STAT(FROZEN, this)) return;
 
@@ -1261,7 +1263,7 @@ void ClientDisconnect(entity this)
 
        Unfreeze(this);
 
-       RemoveGrapplingHook(this);
+       RemoveGrapplingHooks(this);
 
        // Here, everything has been done that requires this player to be a client.
 
@@ -1386,7 +1388,7 @@ void player_powerups(entity this)
        // add a way to see what the items were BEFORE all of these checks for the mutator hook
        int items_prev = this.items;
 
-       if((this.items & IT_USING_JETPACK) && !IS_DEAD(this) && !gameover)
+       if((this.items & IT_USING_JETPACK) && !IS_DEAD(this) && !game_stopped)
                this.modelflags |= MF_ROCKET;
        else
                this.modelflags &= ~MF_ROCKET;
@@ -1692,6 +1694,12 @@ void SpectateCopy(entity this, entity spectatee)
        setsize(this, spectatee.mins, spectatee.maxs);
        SetZoomState(this, spectatee.zoomstate);
 
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               this.(weaponentity) = spectatee.(weaponentity);
+       }
+
     anticheat_spectatecopy(this, spectatee);
        this.hud = spectatee.hud;
        if(spectatee.vehicle)
@@ -2144,7 +2152,7 @@ void PlayerUseKey(entity this)
 
        if(this.vehicle)
        {
-               if(!gameover)
+               if(!game_stopped)
                {
                        vehicles_exit(this.vehicle, VHEF_NORMAL);
                        return;
@@ -2154,7 +2162,7 @@ void PlayerUseKey(entity this)
        {
                if(!STAT(FROZEN, this))
                if(!IS_DEAD(this))
-               if(!gameover)
+               if(!game_stopped)
                {
                        entity head, closest_target = NULL;
                        head = WarpZone_FindRadius(this.origin, autocvar_g_vehicles_enter_radius, true);
@@ -2285,7 +2293,7 @@ void PlayerPreThink (entity this)
 
        MUTATOR_CALLHOOK(PlayerPreThink, this);
 
-       if(autocvar_g_vehicles_enter && (time > this.last_vehiclecheck) && !gameover && !this.vehicle)
+       if(autocvar_g_vehicles_enter && (time > this.last_vehiclecheck) && !game_stopped && !this.vehicle)
        if(IS_PLAYER(this) && !STAT(FROZEN, this) && !IS_DEAD(this))
        {
                FOREACH_ENTITY_RADIUS(this.origin, autocvar_g_vehicles_enter_radius, IS_VEHICLE(it),
@@ -2320,8 +2328,9 @@ void PlayerPreThink (entity this)
        if (IS_PLAYER(this)) {
                CheckRules_Player(this);
 
-               if (intermission_running) {
-                       IntermissionThink(this);
+               if (game_stopped || intermission_running) {
+                       if(intermission_running)
+                               IntermissionThink(this);
                        return;
                }
 
@@ -2406,8 +2415,18 @@ void PlayerPreThink (entity this)
 
                this.prevorigin = this.origin;
 
+               bool have_hook = false;
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(this.(weaponentity).hook.state)
+                       {
+                               have_hook = true;
+                               break;
+                       }
+               }
                bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
-               if (this.hook.state) {
+               if (have_hook) {
                        do_crouch = false;
                } else if (this.waterlevel >= WATERLEVEL_SWIMMING) {
                        do_crouch = false;
@@ -2440,13 +2459,17 @@ void PlayerPreThink (entity this)
                {
                        this.items &= ~this.items_added;
 
-                       //for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-                       //{
-                               //.entity weaponentity = weaponentities[slot];
-                               //W_WeaponFrame(this, weaponentity);
-                       //}
-                       .entity weaponentity = weaponentities[0]; // TODO
-                       W_WeaponFrame(this, weaponentity);
+                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                       {
+                               .entity weaponentity = weaponentities[slot];
+                               W_WeaponFrame(this, weaponentity);
+
+                               if(slot == 0)
+                               {
+                                       this.clip_load = this.(weaponentity).clip_load;
+                                       this.clip_size = this.(weaponentity).clip_size;
+                               }
+                       }
 
                        this.items_added = 0;
                        if (this.items & ITEM_Jetpack.m_itemid && (this.items & ITEM_JetpackRegen.m_itemid || this.ammo_fuel >= 0.01))
@@ -2459,8 +2482,12 @@ void PlayerPreThink (entity this)
 
                // WEAPONTODO: Add a weapon request for this
                // rot vortex charge to the charge limit
-               if (WEP_CVAR(vortex, charge_rot_rate) && this.vortex_charge > WEP_CVAR(vortex, charge_limit) && this.vortex_charge_rottime < time)
-                       this.vortex_charge = bound(WEP_CVAR(vortex, charge_limit), this.vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1);
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if (WEP_CVAR(vortex, charge_rot_rate) && this.(weaponentity).vortex_charge > WEP_CVAR(vortex, charge_limit) && this.(weaponentity).vortex_charge_rottime < time)
+                               this.(weaponentity).vortex_charge = bound(WEP_CVAR(vortex, charge_limit), this.(weaponentity).vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1);
+               }
 
                if (frametime) player_anim(this);
 
@@ -2472,8 +2499,9 @@ void PlayerPreThink (entity this)
 
                this.dmg_team = max(0, this.dmg_team - autocvar_g_teamdamage_resetspeed * frametime);
        }
-       else if (gameover) {
-               if (intermission_running) IntermissionThink(this);
+       else if (game_stopped || intermission_running) {
+               if(intermission_running)
+                       IntermissionThink(this);
                return;
        }
        else if (IS_OBSERVER(this)) {
@@ -2485,11 +2513,15 @@ void PlayerPreThink (entity this)
 
        // WEAPONTODO: Add weapon request for this
        if (!zoomstate_set) {
-               SetZoomState(this,
-                       PHYS_INPUT_BUTTON_ZOOM(this) || PHYS_INPUT_BUTTON_ZOOMSCRIPT(this)
-                       || (PHYS_INPUT_BUTTON_ATCK2(this) && PS(this).m_weapon == WEP_VORTEX)
-                       || (PHYS_INPUT_BUTTON_ATCK2(this) && PS(this).m_weapon == WEP_RIFLE && WEP_CVAR(rifle, secondary) == 0)
-               );
+               bool wep_zoomed = false;
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       Weapon thiswep = this.(weaponentity).m_weapon;
+                       if(thiswep != WEP_Null && thiswep.wr_zoom)
+                               wep_zoomed += thiswep.wr_zoom(thiswep, this);
+               }
+               SetZoomState(this, PHYS_INPUT_BUTTON_ZOOM(this) || PHYS_INPUT_BUTTON_ZOOMSCRIPT(this) || wep_zoomed);
     }
 
        if (this.teamkill_soundtime && time > this.teamkill_soundtime)
@@ -2512,8 +2544,12 @@ void PlayerPreThink (entity this)
 
        // WEAPONTODO: Move into weaponsystem somehow
        // if a player goes unarmed after holding a loaded weapon, empty his clip size and remove the crosshair ammo ring
-       if (PS(this).m_weapon == WEP_Null)
-               this.clip_load = this.clip_size = 0;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               if(this.(weaponentity).m_weapon == WEP_Null)
+                       this.(weaponentity).clip_load = this.(weaponentity).clip_size = 0;
+       }
 }
 
 void DrownPlayer(entity this)
@@ -2615,13 +2651,23 @@ void PlayerPostThink (entity this)
        CheatFrame(this);
 
        //CheckPlayerJump();
+       if (game_stopped)
+       {
+               this.solid = SOLID_NOT;
+               this.takedamage = DAMAGE_NO;
+               set_movetype(this, MOVETYPE_NONE);
+       }
 
        if (IS_PLAYER(this)) {
                DrownPlayer(this);
                CheckRules_Player(this);
                UpdateChatBubble(this);
                if (this.impulse) ImpulseCommands(this);
-               if (intermission_running) return; // intermission or finale
+               if (game_stopped)
+               {
+                       CSQCMODEL_AUTOUPDATE(this);
+                       return;
+               }
                GetPressedKeys(this);
        }