]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/cl_client.qc
Merge remote-tracking branch 'origin/Mario/tweaks'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / cl_client.qc
index 93a63e5ac6c63bd56c58924256186b964bea73e4..d813391bd6e32be463258c7f607ec59d735aca09 100644 (file)
 
 STATIC_METHOD(Client, Add, void(Client this, int _team))
 {
-    WITHSELF(this, ClientConnect());
+    ClientConnect(this);
     TRANSMUTE(Player, this);
     this.frame = 12; // 7
     this.team = _team;
-    WITHSELF(this, PutClientInServer());
+    PutClientInServer(this);
 }
 
 void PutObserverInServer(entity this);
-void ClientDisconnect();
 
 STATIC_METHOD(Client, Remove, void(Client this))
 {
     TRANSMUTE(Observer, this);
-    WITHSELF(this, PutClientInServer());
-    WITHSELF(this, ClientDisconnect());
+    PutClientInServer(this);
+    ClientDisconnect(this);
 }
 
 void send_CSQC_teamnagger() {
@@ -247,7 +246,7 @@ void PutObserverInServer(entity this)
 
        if (this.killcount != FRAGS_SPECTATOR)
        {
-               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_SPECTATE, this.netname);
+               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))
                        Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_CHAT_NOSPECTATORS);
@@ -440,9 +439,8 @@ void FixPlayermodel(entity player)
 
 
 /** Called when a client spawns in the server */
-void PutClientInServer()
+void PutClientInServer(entity this)
 {
-       SELFPARAM(); // needed for engine functions
        if (IS_BOT_CLIENT(this)) {
                TRANSMUTE(Player, this);
        } else if (IS_REAL_CLIENT(this)) {
@@ -711,7 +709,7 @@ void ClientInit_Spawn()
        setthink(e, ClientInit_CheckUpdate);
        Net_LinkEntity(e, false, 0, ClientInit_SendEntity);
 
-       WITHSELF(e, ClientInit_CheckUpdate(e));
+       ClientInit_CheckUpdate(e);
 }
 
 /*
@@ -732,8 +730,8 @@ void SetNewParms ()
 SetChangeParms
 =============
 */
-void SetChangeParms ()
-{SELFPARAM(); // needed for engine functions
+void SetChangeParms (entity this)
+{
        // save parms for level change
        parm1 = this.parm_idlesince - time;
 
@@ -780,7 +778,7 @@ void ClientKill_Now_TeamChange(entity this)
                PutObserverInServer(this);
        }
        else
-               WITHSELF(this, SV_ChangeTeam(this.killindicator_teamchange - 1));
+               SV_ChangeTeam(this, this.killindicator_teamchange - 1);
        this.killindicator_teamchange = 0;
 }
 
@@ -799,12 +797,12 @@ void ClientKill_Now(entity this)
        if(this.killindicator && !wasfreed(this.killindicator))
                remove(this.killindicator);
 
-       this.killindicator = world;
+       this.killindicator = NULL;
 
        if(this.killindicator_teamchange)
                ClientKill_Now_TeamChange(this);
 
-       if(IS_PLAYER(this))
+       if(!IS_SPEC(this) && !IS_OBSERVER(this))
                Damage(this, this, this, 100000, DEATH_KILL.m_id, this.origin, '0 0 0');
 
        // now I am sure the player IS dead
@@ -813,14 +811,14 @@ void KillIndicator_Think(entity this)
 {
        if (gameover)
        {
-               this.owner.killindicator = world;
+               this.owner.killindicator = NULL;
                remove(this);
                return;
        }
 
        if (this.owner.alpha < 0 && !this.owner.vehicle)
        {
-               this.owner.killindicator = world;
+               this.owner.killindicator = NULL;
                remove(this);
                return;
        }
@@ -854,7 +852,6 @@ void ClientKill_TeamChange (entity this, float targetteam) // 0 = don't change,
 {
        float killtime;
        float starttime;
-       entity e;
 
        if (gameover)
                return;
@@ -897,20 +894,20 @@ void ClientKill_TeamChange (entity this, float targetteam) // 0 = don't change,
                        this.killindicator.count = bound(0, ceil(killtime), 10);
                        //sprint(this, strcat("^1You'll be dead in ", ftos(this.killindicator.cnt), " seconds\n"));
 
-                       for(e = world; (e = find(e, classname, "body")) != world; )
+                       FOREACH_ENTITY_ENT(enemy, this,
                        {
-                               if(e.enemy != this)
+                               if(it.classname != "body")
                                        continue;
-                               e.killindicator = spawn();
-                               e.killindicator.owner = e;
-                               e.killindicator.scale = 0.5;
-                               setattachment(e.killindicator, e, "");
-                               setorigin(e.killindicator, '0 0 52');
-                               setthink(e.killindicator, KillIndicator_Think);
-                               e.killindicator.nextthink = starttime + (e.lip) * 0.05;
-                               clientkilltime = max(clientkilltime, e.killindicator.nextthink + 0.05);
-                               e.killindicator.cnt = ceil(killtime);
-                       }
+                               it.killindicator = spawn();
+                               it.killindicator.owner = it;
+                               it.killindicator.scale = 0.5;
+                               setattachment(it.killindicator, it, "");
+                               setorigin(it.killindicator, '0 0 52');
+                               setthink(it.killindicator, KillIndicator_Think);
+                               it.killindicator.nextthink = starttime + (it.lip) * 0.05;
+                               //clientkilltime = max(clientkilltime, it.killindicator.nextthink + 0.05);
+                               it.killindicator.cnt = ceil(killtime);
+                       });
                        this.lip = 0;
                }
        }
@@ -948,8 +945,8 @@ void ClientKill_TeamChange (entity this, float targetteam) // 0 = don't change,
 
 }
 
-void ClientKill ()
-{SELFPARAM(); // needed for engine functions
+void ClientKill (entity this)
+{
        if(gameover) return;
        if(this.player_blocked) return;
        if(STAT(FROZEN, this)) return;
@@ -999,7 +996,7 @@ Called once (not at each match start) when a client begins a connection to the s
 =============
 */
 void ClientPreConnect ()
-{SELFPARAM(); // needed for engine functions
+{ENGINE_EVENT();
        if(autocvar_sv_eventlog)
        {
                GameLogEcho(sprintf(":connect:%d:%d:%s",
@@ -1018,9 +1015,8 @@ ClientConnect
 Called when a client connects to the server
 =============
 */
-void ClientConnect()
+void ClientConnect(entity this)
 {
-       SELFPARAM(); // needed for engine functions
        if (Ban_MaybeEnforceBanOnce(this)) return;
        assert(!IS_CLIENT(this), return);
        this.flags |= FL_CLIENT;
@@ -1175,9 +1171,8 @@ Called when a client disconnects from the server
 */
 .entity chatbubbleentity;
 void ReadyCount();
-void ClientDisconnect()
+void ClientDisconnect(entity this)
 {
-       SELFPARAM(); // needed for engine functions
        assert(IS_CLIENT(this), return);
 
        PlayerStats_GameReport_FinalizePlayer(this);
@@ -1188,7 +1183,7 @@ void ClientDisconnect()
        if (autocvar_sv_eventlog)
                GameLogEcho(strcat(":part:", ftos(this.playerid)));
 
-       Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_DISCONNECT, this.netname);
+       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_DISCONNECT, this.netname);
 
     MUTATOR_CALLHOOK(ClientDisconnect, this);
 
@@ -1226,8 +1221,8 @@ void ChatBubbleThink(entity this)
        this.nextthink = time;
        if ((this.owner.alpha < 0) || this.owner.chatbubbleentity != this)
        {
-               if(this.owner) // but why can that ever be world?
-                       this.owner.chatbubbleentity = world;
+               if(this.owner) // but why can that ever be NULL?
+                       this.owner.chatbubbleentity = NULL;
                remove(this);
                return;
        }
@@ -1304,7 +1299,7 @@ void respawn(entity this)
        CopyBody(this, 1);
 
        this.effects |= EF_NODRAW; // prevent another CopyBody
-       PutClientInServer();
+       PutClientInServer(this);
 }
 
 void play_countdown(entity this, float finished, Sound samp)
@@ -1343,7 +1338,7 @@ void player_powerups(entity this)
                        if (time > this.strength_finished)
                        {
                                this.items = this.items - (this.items & ITEM_Strength.m_itemid);
-                               //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_STRENGTH, this.netname);
+                               //Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERDOWN_STRENGTH, this.netname);
                                Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_POWERDOWN_STRENGTH);
                        }
                }
@@ -1352,7 +1347,7 @@ void player_powerups(entity this)
                        if (time < this.strength_finished)
                        {
                                this.items = this.items | ITEM_Strength.m_itemid;
-                               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_STRENGTH, this.netname);
+                               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERUP_STRENGTH, this.netname);
                                Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_POWERUP_STRENGTH);
                        }
                }
@@ -1363,7 +1358,7 @@ void player_powerups(entity this)
                        if (time > this.invincible_finished)
                        {
                                this.items = this.items - (this.items & ITEM_Shield.m_itemid);
-                               //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_SHIELD, this.netname);
+                               //Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERDOWN_SHIELD, this.netname);
                                Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_POWERDOWN_SHIELD);
                        }
                }
@@ -1372,7 +1367,7 @@ void player_powerups(entity this)
                        if (time < this.invincible_finished)
                        {
                                this.items = this.items | ITEM_Shield.m_itemid;
-                               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SHIELD, this.netname);
+                               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERUP_SHIELD, this.netname);
                                Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_POWERUP_SHIELD);
                        }
                }
@@ -1382,7 +1377,7 @@ void player_powerups(entity this)
                        {
                                this.superweapons_finished = 0;
                                this.items = this.items - (this.items & IT_SUPERWEAPON);
-                               //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_SUPERWEAPON_LOST, this.netname);
+                               //Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_SUPERWEAPON_LOST, this.netname);
                                Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_SUPERWEAPON_LOST);
                        }
                        else if (this.items & IT_UNLIMITED_SUPERWEAPONS)
@@ -1396,7 +1391,7 @@ void player_powerups(entity this)
                                {
                                        this.items = this.items - (this.items & IT_SUPERWEAPON);
                                        this.weapons &= ~WEPSET_SUPERWEAPONS;
-                                       //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_SUPERWEAPON_BROKEN, this.netname);
+                                       //Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_SUPERWEAPON_BROKEN, this.netname);
                                        Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_SUPERWEAPON_BROKEN);
                                }
                        }
@@ -1406,7 +1401,7 @@ void player_powerups(entity this)
                        if (time < this.superweapons_finished || (this.items & IT_UNLIMITED_SUPERWEAPONS))
                        {
                                this.items = this.items | IT_SUPERWEAPON;
-                               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_SUPERWEAPON_PICKUP, this.netname);
+                               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_SUPERWEAPON_PICKUP, this.netname);
                                Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_SUPERWEAPON_PICKUP);
                        }
                        else
@@ -1709,14 +1704,14 @@ bool Spectate(entity this, entity pl)
 
 bool SpectateNext(entity this)
 {
-       other = find(this.enemy, classname, STR_PLAYER);
+       entity ent = find(this.enemy, classname, STR_PLAYER);
 
-       if (MUTATOR_CALLHOOK(SpectateNext, this, other))
-               other = M_ARGV(1, entity);
-       else if (!other)
-               other = find(other, classname, STR_PLAYER);
+       if (MUTATOR_CALLHOOK(SpectateNext, this, ent))
+               ent = M_ARGV(1, entity);
+       else if (!ent)
+               ent = find(ent, classname, STR_PLAYER);
 
-       if(other) { SetSpectatee(this, other); }
+       if(ent) { SetSpectatee(this, ent); }
 
        return SpectateSet(this);
 }
@@ -1724,36 +1719,35 @@ bool SpectateNext(entity this)
 bool SpectatePrev(entity this)
 {
        // NOTE: chain order is from the highest to the lower entnum (unlike find)
-       other = findchain(classname, STR_PLAYER);
-       if (!other) // no player
+       entity ent = findchain(classname, STR_PLAYER);
+       if (!ent) // no player
                return false;
 
-       entity first = other;
+       entity first = ent;
        // skip players until current spectated player
        if(this.enemy)
-       while(other && other != this.enemy)
-               other = other.chain;
+       while(ent && ent != this.enemy)
+               ent = ent.chain;
 
-       switch (MUTATOR_CALLHOOK(SpectatePrev, this, other, first))
+       switch (MUTATOR_CALLHOOK(SpectatePrev, this, ent, first))
        {
                case MUT_SPECPREV_FOUND:
-                   other = M_ARGV(1, entity);
+                   ent = M_ARGV(1, entity);
                    break;
                case MUT_SPECPREV_RETURN:
-                   other = M_ARGV(1, entity);
                    return true;
                case MUT_SPECPREV_CONTINUE:
                default:
                {
-                       if(other.chain)
-                               other = other.chain;
+                       if(ent.chain)
+                               ent = ent.chain;
                        else
-                               other = first;
+                               ent = first;
                        break;
                }
        }
 
-       SetSpectatee(this, other);
+       SetSpectatee(this, ent);
        return SpectateSet(this);
 }
 
@@ -1801,9 +1795,9 @@ void LeaveSpectatorMode(entity this)
 
                        Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_PREVENT_JOIN);
 
-                       WITHSELF(this, PutClientInServer());
+                       PutClientInServer(this);
 
-                       if(IS_PLAYER(this)) { Send_Notification(NOTIF_ALL, world, MSG_INFO, ((teamplay && this.team != -1) ? APP_TEAM_ENT(this, INFO_JOIN_PLAY_TEAM) : INFO_JOIN_PLAY), this.netname); }
+                       if(IS_PLAYER(this)) { Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((teamplay && this.team != -1) ? APP_TEAM_ENT(this, INFO_JOIN_PLAY_TEAM) : INFO_JOIN_PLAY), this.netname); }
                }
                else
                        stuffcmd(this, "menu_showteamselect\n");
@@ -1972,7 +1966,7 @@ void SpectatorThink(entity this)
                                TRANSMUTE(Spectator, this);
                        } else {
                                TRANSMUTE(Observer, this);
-                               WITHSELF(this, PutClientInServer());
+                               PutClientInServer(this);
                        }
                        this.impulse = 0;
                } else if(this.impulse == 12 || this.impulse == 16  || this.impulse == 19 || (this.impulse >= 220 && this.impulse <= 229)) {
@@ -1981,13 +1975,13 @@ void SpectatorThink(entity this)
                                TRANSMUTE(Spectator, this);
                        } else {
                                TRANSMUTE(Observer, this);
-                               WITHSELF(this, PutClientInServer());
+                               PutClientInServer(this);
                        }
                        this.impulse = 0;
                } else if (PHYS_INPUT_BUTTON_ATCK2(this)) {
                        this.flags &= ~FL_JUMPRELEASED;
                        TRANSMUTE(Observer, this);
-                       WITHSELF(this, PutClientInServer());
+                       PutClientInServer(this);
                } else {
                        if(!SpectateUpdate(this))
                                PutObserverInServer(this);
@@ -2029,19 +2023,19 @@ void PlayerUseKey(entity this)
                if(!IS_DEAD(this))
                if(!gameover)
                {
-                       entity head, closest_target = world;
+                       entity head, closest_target = NULL;
                        head = WarpZone_FindRadius(this.origin, autocvar_g_vehicles_enter_radius, true);
 
                        while(head) // find the closest acceptable target to enter
                        {
-                               if(head.vehicle_flags & VHF_ISVEHICLE)
+                               if(IS_VEHICLE(head))
                                if(!IS_DEAD(head))
                                if(!head.owner || ((head.vehicle_flags & VHF_MULTISLOT) && SAME_TEAM(head.owner, this)))
                                if(head.takedamage != DAMAGE_NO)
                                {
                                        if(closest_target)
                                        {
-                                               if(vlen(this.origin - head.origin) < vlen(this.origin - closest_target.origin))
+                                               if(vlen2(this.origin - head.origin) < vlen2(this.origin - closest_target.origin))
                                                { closest_target = head; }
                                        }
                                        else { closest_target = head; }
@@ -2069,9 +2063,8 @@ Called every frame for each client before the physics are run
 .float usekeypressed;
 .float last_vehiclecheck;
 .int items_added;
-void PlayerPreThink ()
+void PlayerPreThink (entity this)
 {
-    SELFPARAM(); // needed for engine functions
        WarpZone_PlayerPhysics_FixVAngle(this);
 
     STAT(GAMESTARTTIME, this) = game_starttime;
@@ -2159,26 +2152,26 @@ void PlayerPreThink ()
 
        MUTATOR_CALLHOOK(PlayerPreThink, this);
 
-       if(autocvar_g_vehicles_enter)
-       if(time > this.last_vehiclecheck)
-       if(IS_PLAYER(this))
-       if(!gameover)
-       if(!STAT(FROZEN, this))
-       if(!this.vehicle)
-       if(!IS_DEAD(this))
+       if(autocvar_g_vehicles_enter && (time > this.last_vehiclecheck) && !gameover && !this.vehicle)
+       if(IS_PLAYER(this) && !STAT(FROZEN, this) && !IS_DEAD(this))
        {
-               entity veh;
-               for(veh = world; (veh = findflags(veh, vehicle_flags, VHF_ISVEHICLE)); )
-               if(vlen(veh.origin - this.origin) < autocvar_g_vehicles_enter_radius)
-               if(!IS_DEAD(veh))
-               if(veh.takedamage != DAMAGE_NO)
-               if((veh.vehicle_flags & VHF_MULTISLOT) && SAME_TEAM(veh.owner, this))
-                       Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_VEHICLE_ENTER_GUNNER);
-               else if(!veh.owner)
-               if(!veh.team || SAME_TEAM(this, veh))
-                       Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_VEHICLE_ENTER);
-               else if(autocvar_g_vehicles_steal)
-                       Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_VEHICLE_ENTER_STEAL);
+               FOREACH_ENTITY_RADIUS(this.origin, autocvar_g_vehicles_enter_radius, IS_VEHICLE(it),
+               {
+                       if(!IS_DEAD(it) && it.takedamage != DAMAGE_NO)
+                       if((it.vehicle_flags & VHF_MULTISLOT) && SAME_TEAM(it.owner, this))
+                       {
+                               Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_VEHICLE_ENTER_GUNNER);
+                       }
+                       else if(!it.owner)
+                       {
+                               if(!it.team || SAME_TEAM(this, it))
+                                       Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_VEHICLE_ENTER);
+                       }
+                       else if(autocvar_g_vehicles_steal)
+                       {
+                               Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_VEHICLE_ENTER_STEAL);
+                       }
+               });
 
                this.last_vehiclecheck = time + 1;
        }
@@ -2394,7 +2387,7 @@ void DrownPlayer(entity this)
        if(IS_DEAD(this))
                return;
 
-       if (this.waterlevel != WATERLEVEL_SUBMERGED)
+       if (this.waterlevel != WATERLEVEL_SUBMERGED || this.vehicle)
        {
                if(this.air_finished < time)
                        PlayerSound(this, playersound_gasp, CH_PLAYER, VOICETYPE_PLAYERSOUND);
@@ -2405,7 +2398,7 @@ void DrownPlayer(entity this)
        {       // drown!
                if (this.pain_finished < time)
                {
-                       Damage (this, world, world, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN.m_id, this.origin, '0 0 0');
+                       Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN.m_id, this.origin, '0 0 0');
                        this.pain_finished = time + 0.5;
                }
        }
@@ -2419,15 +2412,25 @@ Called every frame for each client after the physics are run
 =============
 */
 .float idlekick_lasttimeleft;
-void PlayerPostThink ()
+void PlayerPostThink (entity this)
 {
-    SELFPARAM(); // needed for engine functions
        if (sv_maxidle > 0)
        if (frametime) // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).
        if (IS_REAL_CLIENT(this))
        if (IS_PLAYER(this) || sv_maxidle_spectatorsareidle)
        {
-               if (time - this.parm_idlesince < 1) // instead of (time == this.parm_idlesince) to support sv_maxidle <= 10
+               int totalClients = 0;
+               if(sv_maxidle_slots > 0)
+               {
+                       FOREACH_CLIENT(IS_REAL_CLIENT(it) || sv_maxidle_slots_countbots,
+                       {
+                               ++totalClients;
+                       });
+               }
+
+               if (sv_maxidle_slots > 0 && (maxclients - totalClients) > sv_maxidle_slots)
+               { /* do nothing */ }
+               else if (time - this.parm_idlesince < 1) // instead of (time == this.parm_idlesince) to support sv_maxidle <= 10
                {
                        if (this.idlekick_lasttimeleft)
                        {
@@ -2443,7 +2446,7 @@ void PlayerPostThink ()
                                        Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_DISCONNECT_IDLING, timeleft);
                        }
                        if (timeleft <= 0) {
-                               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_KICK_IDLING, this.netname);
+                               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_KICK_IDLING, this.netname);
                                dropclient(this);
                                return;
                        }