]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/cl_client.qc
csqcplayers: network death_time
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / cl_client.qc
index 2386c3ca9b407a04ac21c6e7c7c6448d8b726b39..d0001b9d39a4845e3b1cd1406ef1d2c29fd787d8 100644 (file)
@@ -123,7 +123,7 @@ void spawnpoint_use()
 // Returns:
 //   _x: prio (-1 if unusable)
 //   _y: weight
-vector Spawn_Score(entity spot, entity playerlist, float teamcheck, float anypoint)
+vector Spawn_Score(entity spot, float mindist, float teamcheck)
 {
        float shortest, thisdist;
        float prio;
@@ -151,55 +151,37 @@ vector Spawn_Score(entity spot, entity playerlist, float teamcheck, float anypoi
                        return '-1 0 0';
        }
 
+       shortest = vlen(world.maxs - world.mins);
+       FOR_EACH_PLAYER(player) if (player != self)
+       {
+               thisdist = vlen(player.origin - spot.origin);
+               if (thisdist < shortest)
+                       shortest = thisdist;
+       }
+       if(shortest > mindist)
+               prio += SPAWN_PRIO_GOOD_DISTANCE;
+
+       spawn_score = prio * '1 0 0' + shortest * '0 1 0';
+       spawn_spot = spot;
+
        // filter out spots for assault
        if(spot.target != "") {
                entity ent;
-               float good, found;
+               float found;
 
                found = 0;
-               good = 0;
                for(ent = world; (ent = find(ent, targetname, spot.target)); )
                {
                        ++found;
-                       if(ent.classname == "target_objective")
-                       {
-                               if(ent.health < 0 || ent.health >= ASSAULT_VALUE_INACTIVE)
-                                       continue;
-                       }
-                       else if(ent.classname == "trigger_race_checkpoint")
+                       if(ent.spawn_evalfunc)
                        {
-                               if(!anypoint) // spectators may spawn everywhere
-                               {
-                                       if(g_race_qualifying)
-                                       {
-                                               // spawn at first
-                                               if(ent.race_checkpoint != 0)
-                                                       continue;
-                                               if(spot.race_place != race_lowest_place_spawn)
-                                                       continue;
-                                       }
-                                       else
-                                       {
-                                               if(ent.race_checkpoint != self.race_respawn_checkpoint)
-                                                       continue;
-                                               // try reusing the previous spawn
-                                               if(ent == self.race_respawn_spotref || spot == self.race_respawn_spotref)
-                                                       prio += 1;
-                                               if(ent.race_checkpoint == 0)
-                                               {
-                                                       float pl;
-                                                       pl = self.race_place;
-                                                       if(pl > race_highest_place_spawn)
-                                                               pl = 0;
-                                                       if(pl == 0 && !self.race_started)
-                                                               pl = race_highest_place_spawn; // use last place if he has not even touched finish yet
-                                                       if(spot.race_place != pl)
-                                                               continue;
-                                               }
-                                       }
-                               }
+                               entity oldself = self;
+                               self = ent;
+                               spawn_score = ent.spawn_evalfunc(oldself, spot, spawn_score);
+                               self = oldself;
+                               if(spawn_score_x < 0)
+                                       return spawn_score;
                        }
-                       ++good;
                }
 
                if(!found)
@@ -207,95 +189,42 @@ vector Spawn_Score(entity spot, entity playerlist, float teamcheck, float anypoi
                        dprint("WARNING: spawnpoint at ", vtos(spot.origin), " could not find its target ", spot.target, "\n");
                        return '-1 0 0';
                }
-
-               if(good < found) // at least one was bad
-                       return '-1 0 0';
        }
 
-       player = playerlist;
-       shortest = vlen(world.maxs - world.mins);
-       for(player = playerlist; player; player = player.chain)
-               if (player != self)
-               {
-                       thisdist = vlen(player.origin - spot.origin);
-                       if (thisdist < shortest)
-                               shortest = thisdist;
-               }
-       return prio * '1 0 0' + shortest * '0 1 0';
+       MUTATOR_CALLHOOK(Spawn_Score);
+       return spawn_score;
+}
+
+void Spawn_ScoreAll(entity firstspot, float mindist, float teamcheck)
+{
+       entity spot;
+       for(spot = firstspot; spot; spot = spot.chain)
+               spot.spawnpoint_score = Spawn_Score(spot, mindist, teamcheck);
 }
 
-float spawn_allbad;
-float spawn_allgood;
-entity Spawn_FilterOutBadSpots(entity firstspot, entity playerlist, float mindist, float teamcheck, float anypoint)
+entity Spawn_FilterOutBadSpots(entity firstspot, float mindist, float teamcheck)
 {
        entity spot, spotlist, spotlistend;
-       spawn_allgood = TRUE;
-       spawn_allbad = TRUE;
 
        spotlist = world;
        spotlistend = world;
 
+       Spawn_ScoreAll(firstspot, mindist, teamcheck);
+
        for(spot = firstspot; spot; spot = spot.chain)
        {
-               spot.spawnpoint_score = Spawn_Score(spot, playerlist, teamcheck, anypoint);
-
-               if(autocvar_spawn_debugview)
-               {
-                       setmodel(spot, "models/runematch/rune.mdl");
-                       if(spot.spawnpoint_score_y < mindist)
-                       {
-                               spot.colormod = '1 0 0';
-                               spot.scale = 1;
-                       }
-                       else
-                       {
-                               spot.colormod = '0 1 0';
-                               spot.scale = spot.spawnpoint_score_y / mindist;
-                       }
-               }
-
                if(spot.spawnpoint_score_x >= 0) // spawning allowed here
                {
-                       if(spot.spawnpoint_score_y < mindist)
-                       {
-                               // too short distance
-                               spawn_allgood = FALSE;
-                       }
-                       else
-                       {
-                               // perfect
-                               spawn_allbad = FALSE;
-
-                               if(spotlistend)
-                                       spotlistend.chain = spot;
-                               spotlistend = spot;
-                               if(!spotlist)
-                                       spotlist = spot;
-
-                               /*
-                               if(teamcheck >= 0)
-                               if(spot.team != teamcheck)
-                                       error("invalid spawn added");
-
-                               print("added ", etos(spot), "\n");
-                               */
-                       }
+                       if(spotlistend)
+                               spotlistend.chain = spot;
+                       spotlistend = spot;
+                       if(!spotlist)
+                               spotlist = spot;
                }
        }
        if(spotlistend)
                spotlistend.chain = world;
 
-       /*
-               entity e;
-               if(teamcheck >= 0)
-                       for(e = spotlist; e; e = e.chain)
-                       {
-                               print("seen ", etos(e), "\n");
-                               if(e.team != teamcheck)
-                                       error("invalid spawn found");
-                       }
-       */
-
        return spotlist;
 }
 
@@ -322,8 +251,7 @@ Finds a point to respawn
 entity SelectSpawnPoint (float anypoint)
 {
        float teamcheck;
-       entity firstspot_new;
-       entity spot, firstspot, playerlist;
+       entity spot, firstspot;
 
        spot = find (world, classname, "testplayerstart");
        if (spot)
@@ -354,8 +282,6 @@ entity SelectSpawnPoint (float anypoint)
                // if we get here, we either require team spawns but have none, or we require non-team spawns and have none; use any spawn then
 
 
-       // get the list of players
-       playerlist = findchain(classname, "player");
        // get the entire list of spots
        firstspot = findchain(classname, "info_player_deathmatch");
        // filter out the bad ones
@@ -366,42 +292,26 @@ entity SelectSpawnPoint (float anypoint)
        }
        else
        {
-               firstspot_new = Spawn_FilterOutBadSpots(firstspot, playerlist, 100, teamcheck, anypoint);
-               if(!firstspot_new)
-                       firstspot_new = Spawn_FilterOutBadSpots(firstspot, playerlist, -1, teamcheck, anypoint);
-               firstspot = firstspot_new;
+               float mindist;
+               if (arena_roundbased && !g_ca)
+                       mindist = 800;
+               else
+                       mindist = 100;
+               firstspot = Spawn_FilterOutBadSpots(firstspot, mindist, teamcheck);
 
                // there is 50/50 chance of choosing a random spot or the furthest spot
                // (this means that roughly every other spawn will be furthest, so you
                // usually won't get fragged at spawn twice in a row)
-               if (arena_roundbased && !g_ca)
-               {
-                       firstspot_new = Spawn_FilterOutBadSpots(firstspot, playerlist, 800, teamcheck, anypoint);
-                       if(firstspot_new)
-                               firstspot = firstspot_new;
-                       spot = Spawn_WeightedPoint(firstspot, 1, 1, 1);
-               }
-               else if (random() > autocvar_g_spawn_furthest)
+               if (random() > autocvar_g_spawn_furthest)
                        spot = Spawn_WeightedPoint(firstspot, 1, 1, 1);
                else
                        spot = Spawn_WeightedPoint(firstspot, 1, 5000, 5); // chooses a far far away spawnpoint
        }
 
-       if(autocvar_spawn_debugview)
-       {
-               print("spot mindistance: ", vtos(spot.spawnpoint_score), "\n");
-
-               entity e;
-               if(teamcheck >= 0)
-                       for(e = firstspot; e; e = e.chain)
-                               if(e.team != teamcheck)
-                                       error("invalid spawn found");
-       }
-
        if (!spot)
        {
                if(autocvar_spawn_debug)
-                       GotoNextMap();
+                       GotoNextMap(0);
                else
                {
                        if(some_spawn_has_been_used)
@@ -431,25 +341,26 @@ string CheckPlayerModel(string plyermodel) {
                // to change a cvar default, we'll have a small leak here.
                FallbackPlayerModel = strzone(cvar_defstring("_cl_playermodel"));
        }
-       if(strlen(plyermodel) < 4)
-               return FallbackPlayerModel;
+       // only in right path
        if( substring(plyermodel,0,14) != "models/player/")
                return FallbackPlayerModel;
-       else if(autocvar_sv_servermodelsonly)
+       // only good file extensions
+       if(substring(plyermodel,-4,4) != ".zym")
+       if(substring(plyermodel,-4,4) != ".dpm")
+       if(substring(plyermodel,-4,4) != ".iqm")
+       if(substring(plyermodel,-4,4) != ".md3")
+       if(substring(plyermodel,-4,4) != ".psk")
+               return FallbackPlayerModel;
+       // forbid the LOD models
+       if(substring(plyermodel, -9,5) == "_lod1")
+               return FallbackPlayerModel;
+       if(substring(plyermodel, -9,5) == "_lod2")
+               return FallbackPlayerModel;
+       if(plyermodel != strtolower(plyermodel))
+               return FallbackPlayerModel;
+       // also, restrict to server models
+       if(autocvar_sv_servermodelsonly)
        {
-               if(substring(plyermodel,-4,4) != ".zym")
-               if(substring(plyermodel,-4,4) != ".dpm")
-               if(substring(plyermodel,-4,4) != ".iqm")
-               if(substring(plyermodel,-4,4) != ".md3")
-               if(substring(plyermodel,-4,4) != ".psk")
-                       return FallbackPlayerModel;
-               // forbid the LOD models
-               if(substring(plyermodel, -9,5) == "_lod1")
-                       return FallbackPlayerModel;
-               if(substring(plyermodel, -9,5) == "_lod2")
-                       return FallbackPlayerModel;
-               if(plyermodel != strtolower(plyermodel))
-                       return FallbackPlayerModel;
                if(!fexists(plyermodel))
                        return FallbackPlayerModel;
        }
@@ -545,7 +456,7 @@ void PutObserverInServer (void)
        self.health = -666;
        self.takedamage = DAMAGE_NO;
        self.solid = SOLID_NOT;
-       self.movetype = MOVETYPE_FLY_WORLDONLY; //(self.cvar_cl_clippedspectating ? MOVETYPE_NOCLIP : MOVETYPE_FLY); // it's too early for this anyway, lets just set it in playerprethink
+       self.movetype = MOVETYPE_FLY_WORLDONLY; // user preference is controlled by playerprethink
        self.flags = FL_CLIENT | FL_NOTARGET;
        self.armorvalue = 666;
        self.effects = 0;
@@ -555,7 +466,7 @@ void PutObserverInServer (void)
        self.pauseregen_finished = 0;
        self.damageforcescale = 0;
        self.death_time = 0;
-       self.dead_frame = 0;
+       self.respawn_time = 0;
        self.alpha = 0;
        self.scale = 0;
        self.fade_time = 0;
@@ -574,7 +485,7 @@ void PutObserverInServer (void)
        self.fixangle = TRUE;
        self.crouch = FALSE;
 
-       setorigin (self, spot.origin);
+       setorigin (self, (spot.origin + PL_VIEW_OFS)); // offset it so that the spectator spawns higher off the ground, looks better this way
        self.prevorigin = self.origin;
        self.items = 0;
        self.weapons = 0;
@@ -673,13 +584,6 @@ void FixPlayermodel()
                }
        }
 
-       if(self.modelindex == 0 && self.deadflag == DEAD_NO)
-       {
-               if(self.model != "")
-                       bprint("\{1}^1Player ", self.netname, "^1 has a zero modelindex, trying to fix...\n");
-               self.model = ""; // force the != checks to return true
-       }
-
        if(defaultmodel != "")
        {
                if (defaultmodel != self.model)
@@ -856,7 +760,6 @@ void PutClientInServer (void)
                }
 
                self.items = start_items;
-               self.jump_interval = time;
 
                self.spawnshieldtime = time + autocvar_g_spawnshieldtime;
                self.pauserotarmor_finished = time + autocvar_g_balance_pause_armor_rot_spawn;
@@ -872,8 +775,7 @@ void PutClientInServer (void)
                }
                self.damageforcescale = 2;
                self.death_time = 0;
-               self.dead_frame = 0;
-               self.alpha = 0;
+               self.respawn_time = 0;
                self.scale = 0;
                self.fade_time = 0;
                self.pain_frame = 0;
@@ -959,12 +861,6 @@ void PutClientInServer (void)
 
                race_PostSpawn(spot);
 
-               if(autocvar_spawn_debug)
-               {
-                       sprint(self, strcat("spawnpoint origin:  ", vtos(spot.origin), "\n"));
-                       remove(spot);   // usefull for checking if there are spawnpoints, that let drop through the floor
-               }
-
                //stuffcmd(self, "chase_active 0");
                //stuffcmd(self, "set viewsize $tmpviewsize \n");
 
@@ -1003,8 +899,15 @@ void PutClientInServer (void)
                        activator = world;
                self = oldself;
 
+               spawn_spot = spot;
                MUTATOR_CALLHOOK(PlayerSpawn);
 
+               if(autocvar_spawn_debug)
+               {
+                       sprint(self, strcat("spawnpoint origin:  ", vtos(spot.origin), "\n"));
+                       remove(spot);   // usefull for checking if there are spawnpoints, that let drop through the floor
+               }
+
                self.switchweapon = w_getbestweapon(self);
                self.cnt = -1; // W_LastWeapon will not complain
                self.weapon = 0;
@@ -1013,6 +916,8 @@ void PutClientInServer (void)
 
                if(!self.alivetime)
                        self.alivetime = time;
+
+               antilag_clear(self);
        } else if(self.classname == "observer" || (g_ca && !allowed_to_spawn)) {
                PutObserverInServer ();
        }
@@ -1209,7 +1114,7 @@ void KillIndicator_Think()
                return;
        }
 
-       if (!self.owner.modelindex)
+       if (self.owner.alpha < 0)
        {
                self.owner.killindicator = world;
                remove(self);
@@ -1269,7 +1174,7 @@ void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto, -2
 
     if(!self.killindicator)
        {
-               if(self.modelindex && self.deadflag == DEAD_NO)
+               if(self.deadflag == DEAD_NO)
                {
                        killtime = max(killtime, self.clientkill_nexttime - time);
                        self.clientkill_nexttime = time + killtime + autocvar_g_balance_kill_antispam;
@@ -1424,10 +1329,6 @@ float PlayerInIDList(entity p, string idlist)
        return 0;
 }
 
-#ifndef NO_LEGACY_NETWORKING
-.float iscsqcmodel;
-#endif
-
 /*
 =============
 ClientConnect
@@ -1601,8 +1502,6 @@ void ClientConnect (void)
        else
                stuffcmd(self, "set _teams_available 0\n");
 
-       stuffcmd(self, strcat("set gametype ", ftos(game), "\n"));
-
        if(g_arena || g_ca)
        {
                self.classname = "observer";
@@ -1625,7 +1524,7 @@ void ClientConnect (void)
        }
 
        self.jointime = time;
-       self.allowedTimeouts = autocvar_sv_timeout_number;
+       self.allowed_timeouts = autocvar_sv_timeout_number;
 
        if(clienttype(self) == CLIENTTYPE_REAL)
        {
@@ -1687,15 +1586,7 @@ void ClientConnect (void)
        if(!autocvar_g_campaign)
                Send_CSQC_Centerprint_Generic(self, CPID_MOTD, getwelcomemessage(), autocvar_welcome_message_time, 0);
 
-#ifndef NO_LEGACY_NETWORKING
-       if(autocvar_sv_use_csqc_players)
-       {
-               CSQCModel_LinkEntity();
-               self.iscsqcmodel = 1;
-       }
-#else
-       CSQCModel_LinkEntity();
-#endif
+       CSQCMODEL_AUTOINIT();
 
        self.model_randomizer = random();
 }
@@ -1805,7 +1696,7 @@ void ClientDisconnect (void)
 void ChatBubbleThink()
 {
        self.nextthink = time;
-       if (!self.owner.modelindex || self.owner.chatbubbleentity != self)
+       if ((self.owner.alpha < 0) || self.owner.chatbubbleentity != self)
        {
                if(self.owner) // but why can that ever be world?
                        self.owner.chatbubbleentity = world;
@@ -1824,7 +1715,7 @@ void ChatBubbleThink()
 
 void UpdateChatBubble()
 {
-       if (!self.modelindex)
+       if (self.alpha < 0)
                return;
        // spawn a chatbubble entity if needed
        if (!self.chatbubbleentity)
@@ -1861,10 +1752,9 @@ void UpdateChatBubble()
        else self.colormod = '1 1 1';
 }*/
 
-.float oldcolormap;
 void respawn(void)
 {
-       if(self.modelindex != 0 && autocvar_g_respawn_ghosts)
+       if(self.alpha >= 0 && autocvar_g_respawn_ghosts)
        {
                self.solid = SOLID_NOT;
                self.takedamage = DAMAGE_NO;
@@ -1872,7 +1762,7 @@ void respawn(void)
                self.velocity = '0 0 1' * autocvar_g_respawn_ghosts_speed;
                self.avelocity = randomvec() * autocvar_g_respawn_ghosts_speed * 3 - randomvec() * autocvar_g_respawn_ghosts_speed * 3;
                self.effects |= EF_ADDITIVE;
-               self.oldcolormap = self.colormap;
+               self.oldcolormap = self.colormap; // saved for copybody to use later
                self.colormap = 0; // this originally was 512, but raises a warning in the engine, so get rid of it
                pointparticles(particleeffectnum("respawn_ghost"), self.origin, '0 0 0', 1);
                if(autocvar_g_respawn_ghosts_maxtime)
@@ -1881,11 +1771,13 @@ void respawn(void)
 
        CopyBody(1);
        self.effects |= EF_NODRAW; // prevent another CopyBody
-       if(self.oldcolormap)
+       
+       if(self.oldcolormap) // reset it so that when they respawn it'll be back to normal
        {
                self.colormap = self.oldcolormap;
                self.oldcolormap = 0;
        }
+       
        PutClientInServer();
 }
 
@@ -1913,9 +1805,9 @@ void player_powerups (void)
                self.modelflags &~= MF_ROCKET;
        }
 
-       self.effects &~= (EF_DIMLIGHT | EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT | EF_FLAME | EF_NODEPTHTEST);
+       self.effects &~= (EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT | EF_FLAME | EF_NODEPTHTEST);
 
-       if(!self.modelindex || self.deadflag) // don't apply the flags if the player is gibbed
+       if(self.alpha < 0 || self.deadflag) // don't apply the flags if the player is gibbed
                return;
 
        Fire_ApplyDamage(self);
@@ -1950,7 +1842,7 @@ void player_powerups (void)
                if (self.items & IT_INVINCIBLE)
                {
                        play_countdown(self.invincible_finished, "misc/poweroff.wav");
-                       if (time > self.invincible_finished && autocvar_g_balance_powerup_timer)
+                       if (time > self.invincible_finished)
                        {
                                self.items = self.items - (self.items & IT_INVINCIBLE);
                                sprint(self, "^3Speed has worn off\n");
@@ -1971,7 +1863,7 @@ void player_powerups (void)
                {
                        play_countdown(self.strength_finished, "misc/poweroff.wav");
                        self.effects = self.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT);
-                       if (time > self.strength_finished && autocvar_g_balance_powerup_timer)
+                       if (time > self.strength_finished)
                        {
                                self.items = self.items - (self.items & IT_STRENGTH);
                                sprint(self, "^3Strength has worn off\n");
@@ -1989,7 +1881,7 @@ void player_powerups (void)
                {
                        play_countdown(self.invincible_finished, "misc/poweroff.wav");
                        self.effects = self.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT);
-                       if (time > self.invincible_finished && autocvar_g_balance_powerup_timer)
+                       if (time > self.invincible_finished)
                        {
                                self.items = self.items - (self.items & IT_INVINCIBLE);
                                sprint(self, "^3Shield has worn off\n");
@@ -2003,26 +1895,26 @@ void player_powerups (void)
                                sprint(self, "^3Shield surrounds you\n");
                        }
                }
+       }
+       
+       if(autocvar_g_nodepthtestplayers)
+               self.effects = self.effects | EF_NODEPTHTEST;
 
-               if(autocvar_g_nodepthtestplayers)
-                       self.effects = self.effects | EF_NODEPTHTEST;
-
-               if(autocvar_g_fullbrightplayers)
-                       self.effects = self.effects | EF_FULLBRIGHT;
+       if(autocvar_g_fullbrightplayers)
+               self.effects = self.effects | EF_FULLBRIGHT;
 
-               // midair gamemode: damage only while in the air
-               // if in midair mode, being on ground grants temporary invulnerability
-               // (this is so that multishot weapon don't clear the ground flag on the
-               // first damage in the frame, leaving the player vulnerable to the
-               // remaining hits in the same frame)
-               if (self.flags & FL_ONGROUND)
-               if (g_midair)
-                       self.spawnshieldtime = max(self.spawnshieldtime, time + autocvar_g_midair_shieldtime);
+       // midair gamemode: damage only while in the air
+       // if in midair mode, being on ground grants temporary invulnerability
+       // (this is so that multishot weapon don't clear the ground flag on the
+       // first damage in the frame, leaving the player vulnerable to the
+       // remaining hits in the same frame)
+       if (self.flags & FL_ONGROUND)
+       if (g_midair)
+               self.spawnshieldtime = max(self.spawnshieldtime, time + autocvar_g_midair_shieldtime);
 
-               if (time >= game_starttime)
-               if (time < self.spawnshieldtime)
-                       self.effects = self.effects | (EF_ADDITIVE | EF_FULLBRIGHT);
-       }
+       if (time >= game_starttime)
+       if (time < self.spawnshieldtime)
+               self.effects = self.effects | (EF_ADDITIVE | EF_FULLBRIGHT);
 
        MUTATOR_CALLHOOK(PlayerPowerups);
 }
@@ -2366,13 +2258,13 @@ void ShowRespawnCountdown()
                return;
        else
        {
-               number = ceil(self.death_time - time);
+               number = ceil(self.respawn_time - time);
                if(number <= 0)
                        return;
                if(number <= self.respawn_countdown)
                {
                        self.respawn_countdown = number - 1;
-                       if(ceil(self.death_time - (time + 0.5)) == number) // only say it if it is the same number even in 0.5s; to prevent overlapping sounds
+                       if(ceil(self.respawn_time - (time + 0.5)) == number) // only say it if it is the same number even in 0.5s; to prevent overlapping sounds
                                AnnounceTo(self, strcat(ftos(number), ""));
                }
        }
@@ -2708,7 +2600,7 @@ void PlayerPreThink (void)
                }
 
                //don't allow the player to turn around while game is paused!
-               if(timeoutStatus == 2) {
+               if(timeout_status == TIMEOUT_ACTIVE) {
                        // FIXME turn this into CSQC stuff
                        self.v_angle = self.lastV_angle;
                        self.angles = self.lastV_angle;
@@ -2748,9 +2640,9 @@ void PlayerPreThink (void)
                        float button_pressed, force_respawn;
                        if(self.personal && g_race_qualifying)
                        {
-                               if(time > self.death_time)
+                               if(time > self.respawn_time)
                                {
-                                       self.death_time = time + 1; // only retry once a second
+                                       self.respawn_time = time + 1; // only retry once a second
                                        respawn();
                                        self.impulse = 141;
                                }
@@ -2780,9 +2672,9 @@ void PlayerPreThink (void)
                                }
                                else if (self.deadflag == DEAD_RESPAWNING)
                                {
-                                       if(time > self.death_time)
+                                       if(time > self.respawn_time)
                                        {
-                                               self.death_time = time + 1; // only retry once a second
+                                               self.respawn_time = time + 1; // only retry once a second
                                                respawn();
                                        }
                                }
@@ -3028,10 +2920,8 @@ void PlayerPostThink (void)
                stuffcmd(self, strcat("name ", self.netname, substring(ftos(random()), 2, -1), "\n"));
        }
 
-       if(sv_maxidle && frametime)
+       if(sv_maxidle && frametime) // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).
        {
-               // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).
-               float timeleft;
                if (time - self.parm_idlesince < 1) // instead of (time == self.parm_idlesince) to support sv_maxidle <= 10
                {
                        if(self.idlekick_lasttimeleft)
@@ -3039,34 +2929,37 @@ void PlayerPostThink (void)
                                Send_CSQC_Centerprint_Generic_Expire(self, CPID_DISCONNECT_IDLING);
                                self.idlekick_lasttimeleft = 0;
                        }
-                       return;
-               }
-               timeleft = ceil(sv_maxidle - (time - self.parm_idlesince));
-               if(timeleft == min(10, sv_maxidle - 1)) // - 1 to support sv_maxidle <= 10
-               {
-                       if(!self.idlekick_lasttimeleft)
-                               Send_CSQC_Centerprint_Generic(self, CPID_DISCONNECT_IDLING, "^3Stop idling!\n^3Disconnecting in %d seconds...", 1, timeleft);
-               }
-               if(timeleft <= 0)
-               {
-                       bprint("^3", self.netname, "^3 was kicked for idling.\n");
-                       AnnounceTo(self, "terminated");
-                       dropclient(self);
-                       return;
                }
-               else if(timeleft <= 10)
+               else
                {
-                       if(timeleft != self.idlekick_lasttimeleft)
-                               AnnounceTo(self, ftos(timeleft));
-                       self.idlekick_lasttimeleft = timeleft;
+                       float timeleft;
+                       timeleft = ceil(sv_maxidle - (time - self.parm_idlesince));
+                       if(timeleft == min(10, sv_maxidle - 1)) // - 1 to support sv_maxidle <= 10
+                       {
+                               if(!self.idlekick_lasttimeleft)
+                                       Send_CSQC_Centerprint_Generic(self, CPID_DISCONNECT_IDLING, "^3Stop idling!\n^3Disconnecting in %d seconds...", 1, timeleft);
+                       }
+                       if(timeleft <= 0)
+                       {
+                               bprint("^3", self.netname, "^3 was kicked for idling.\n");
+                               AnnounceTo(self, "terminated");
+                               dropclient(self);
+                               return;
+                       }
+                       else if(timeleft <= 10)
+                       {
+                               if(timeleft != self.idlekick_lasttimeleft)
+                                       AnnounceTo(self, ftos(timeleft));
+                               self.idlekick_lasttimeleft = timeleft;
+                       }
                }
        }
 
 #ifdef TETRIS
        if(self.impulse == 100)
                ImpulseCommands();
-       if (TetrisPostFrame())
-               return;
+       if (!TetrisPostFrame())
+       {
 #endif
 
        CheatFrame();
@@ -3087,6 +2980,10 @@ void PlayerPostThink (void)
                //do nothing
        }
        
+#ifdef TETRIS
+       }
+#endif
+
        /*
        float i;
        for(i = 0; i < 1000; ++i)
@@ -3150,22 +3047,5 @@ void PlayerPostThink (void)
                dprint(sprintf("%f %.6f\n", time, race_GetFractionalLapCount(self)));
        */
 
-#ifndef NO_LEGACY_NETWORKING
-       if(autocvar_sv_use_csqc_players && !self.iscsqcmodel)
-       {
-               CSQCModel_LinkEntity();
-               self.iscsqcmodel = 1;
-       }
-
-       if(!autocvar_sv_use_csqc_players && self.iscsqcmodel)
-       {
-               CSQCModel_UnlinkEntity();
-               self.iscsqcmodel = 0;
-       }
-
-       if(self.iscsqcmodel)
-               CSQCModel_CheckUpdate();
-#else
-       CSQCModel_CheckUpdate();
-#endif
+       CSQCMODEL_AUTOUPDATE();
 }