]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/cl_client.qc
Merge branch 'master' into Mario/showspecs
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / cl_client.qc
index 7644895d0dc82a40fd23ea258167b2f6a498f028..fe12ffc0393134d27b7311ec0b612e562bc98a0f 100644 (file)
@@ -1,14 +1,72 @@
+#include "waypointsprites.qh"
+
+#include "cl_impulse.qh"
+#include "cl_player.qh"
+#include "ent_cs.qh"
+#include "g_subs.qh"
+#include "ipban.qh"
+#include "miscfunctions.qh"
+#include "portals.qh"
+#include "teamplay.qh"
+#include "playerdemo.qh"
+#include "secret.qh"
+
+#include "bot/bot.qh"
+#include "bot/navigation.qh"
+
+#include "weapons/hitplot.qh"
+#include "weapons/weaponsystem.qh"
+
+#include "../common/net_notice.qh"
+
+#include "../common/monsters/sv_monsters.qh"
+
+#include "../warpzonelib/server.qh"
+
+float c1, c2, c3, c4;
+
 void send_CSQC_teamnagger() {
        WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
        WriteByte(MSG_BROADCAST, TE_CSQC_TEAMNAGGER);
 }
 
-float ClientData_Send(entity to, float sf)
+int CountSpectators(entity player, entity to)
+{
+       if(!player) { return 0; } // not sure how, but best to be safe
+
+       entity head;
+       float spec_count = 0;
+       FOR_EACH_REALCLIENT(head)
+       {
+               if(IS_SPEC(head))
+               if(head != to)
+               if(head.enemy == player)
+                       spec_count += 1;
+       }
+
+       return spec_count;
+}
+
+void WriteSpectators(entity player, entity to)
+{
+       if(!player) { return; } // not sure how, but best to be safe
+
+       entity head;
+       FOR_EACH_REALCLIENT(head)
+       {
+               if(IS_SPEC(head))
+               if(head != to)
+               if(head.enemy == player)
+                       WriteByte(MSG_ENTITY, num_for_edict(head));
+       }
+}
+
+bool ClientData_Send(entity to, int sf)
 {
        if(to != self.owner)
        {
                error("wtf");
-               return FALSE;
+               return false;
        }
 
        entity e;
@@ -27,6 +85,8 @@ float ClientData_Send(entity to, float sf)
                sf |= 4; // zoomed
        if(e.porto_v_angle_held)
                sf |= 8; // angles held
+       // always check spectators
+       sf |= 16; // spectator handling?
 
        WriteByte(MSG_ENTITY, ENT_CLIENT_CLIENTDATA);
        WriteByte(MSG_ENTITY, sf);
@@ -36,16 +96,23 @@ float ClientData_Send(entity to, float sf)
 
        if(sf & 8)
        {
-               WriteAngle(MSG_ENTITY, e.v_angle_x);
-               WriteAngle(MSG_ENTITY, e.v_angle_y);
+               WriteAngle(MSG_ENTITY, e.v_angle.x);
+               WriteAngle(MSG_ENTITY, e.v_angle.y);
        }
 
-       return TRUE;
+       if(sf & 16)
+       {
+               float specs = CountSpectators(e, to);
+               WriteByte(MSG_ENTITY, specs);
+               WriteSpectators(e, to);
+       }
+
+       return true;
 }
 
 void ClientData_Attach()
 {
-       Net_LinkEntity(self.clientdata = spawn(), FALSE, 0, ClientData_Send);
+       Net_LinkEntity(self.clientdata = spawn(), false, 0, ClientData_Send);
        self.clientdata.drawonlytoclient = self;
        self.clientdata.owner = self;
 }
@@ -73,6 +140,8 @@ void ClientData_Touch(entity e)
 
 .string netname_previous;
 
+void SetSpectator(entity player, entity spectatee);
+
 
 /*
 =============
@@ -135,12 +204,15 @@ putting a client as observer in the server
 void FixPlayermodel();
 void PutObserverInServer (void)
 {
-       entity  spot;
+       entity spot;
+
+       SetSpectator(self, world);
+
     self.hud = HUD_NORMAL;
 
        if(IS_PLAYER(self)) { pointparticles(particleeffectnum("spawn_event_neutral"), self.origin, '0 0 0', 1); }
 
-       spot = SelectSpawnPoint (TRUE);
+       spot = SelectSpawnPoint (true);
        if(!spot)
                error("No spawnpoints for observers?!?\n");
        RemoveGrapplingHook(self); // Wazat's Grappling Hook
@@ -163,7 +235,7 @@ void PutObserverInServer (void)
        if(self.alivetime)
        {
                if(!warmup_stage)
-                       PlayerStats_Event(self, PLAYERSTATS_ALIVETIME, time - self.alivetime);
+                       PS_GR_P_ADDVAL(self, PLAYERSTATS_ALIVETIME, time - self.alivetime);
                self.alivetime = 0;
        }
 
@@ -181,10 +253,10 @@ void PutObserverInServer (void)
                if(autocvar_g_chat_nospectators == 1 || (cvar("g_warmup") && !(warmup_stage || gameover) && autocvar_g_chat_nospectators == 2))
                        Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_CHAT_NOSPECTATORS);
 
-               if(self.just_joined == FALSE) {
+               if(self.just_joined == false) {
                        LogTeamchange(self.playerid, -1, 4);
                } else
-                       self.just_joined = FALSE;
+                       self.just_joined = false;
        }
 
        PlayerScore_Clear(self); // clear scores when needed
@@ -194,9 +266,9 @@ void PutObserverInServer (void)
        self.spectatortime = time;
 
        self.classname = "observer";
-       self.iscreature = FALSE;
+       self.iscreature = false;
        self.teleportable = TELEPORT_SIMPLE;
-       self.damagedbycontents = FALSE;
+       self.damagedbycontents = false;
        self.health = -666;
        self.takedamage = DAMAGE_NO;
        self.solid = SOLID_NOT;
@@ -229,8 +301,8 @@ void PutObserverInServer (void)
        self.deadflag = DEAD_NO;
        self.angles = spot.angles;
        self.angles_z = 0;
-       self.fixangle = TRUE;
-       self.crouch = FALSE;
+       self.fixangle = true;
+       self.crouch = false;
        self.revival_time = 0;
 
        setorigin (self, (spot.origin + PL_VIEW_OFS)); // offset it so that the spectator spawns higher off the ground, looks better this way
@@ -258,6 +330,7 @@ void PutObserverInServer (void)
        self.punchvector = '0 0 0';
        self.oldvelocity = self.velocity;
        self.fire_endtime = -1;
+       self.event_damage = func_null;
 }
 
 .float model_randomizer;
@@ -269,7 +342,7 @@ void FixPlayermodel()
 
        defaultmodel = "";
        defaultskin = 0;
-       chmdl = FALSE;
+       chmdl = false;
 
        if(autocvar_sv_defaultcharacter == 1)
        {
@@ -316,7 +389,7 @@ void FixPlayermodel()
                        m2 = self.maxs;
                        setplayermodel (self, defaultmodel);
                        setsize (self, m1, m2);
-                       chmdl = TRUE;
+                       chmdl = true;
                }
 
                oldskin = self.skin;
@@ -329,7 +402,7 @@ void FixPlayermodel()
                        m2 = self.maxs;
                        setplayermodel (self, self.playermodel);
                        setsize (self, m1, m2);
-                       chmdl = TRUE;
+                       chmdl = true;
                }
 
                oldskin = self.skin;
@@ -366,6 +439,8 @@ void PutClientInServer (void)
                WriteEntity(MSG_ONE, self);
        }
 
+       SetSpectator(self, world);
+
        // reset player keys
        self.itemkeys = 0;
 
@@ -382,9 +457,9 @@ void PutClientInServer (void)
                accuracy_resend(self);
 
                if(self.team < 0)
-                       JoinBestTeam(self, FALSE, TRUE);
+                       JoinBestTeam(self, false, true);
 
-               spot = SelectSpawnPoint (FALSE);
+               spot = SelectSpawnPoint (false);
                if(!spot)
                {
                        Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_JOIN_NOSPAWNS);
@@ -397,10 +472,10 @@ void PutClientInServer (void)
                        vehicles_exit(VHEF_RELESE);
 
                self.classname = "player";
-               self.wasplayer = TRUE;
-               self.iscreature = TRUE;
+               self.wasplayer = true;
+               self.iscreature = true;
                self.teleportable = TELEPORT_NORMAL;
-               self.damagedbycontents = TRUE;
+               self.damagedbycontents = true;
                self.movetype = MOVETYPE_WALK;
                self.solid = SOLID_SLIDEBOX;
                self.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_SOLID;
@@ -419,11 +494,11 @@ void PutClientInServer (void)
                self.effects |= EF_TELEPORT_BIT | EF_RESTARTANIM_BIT;
                self.air_finished = time + 12;
                self.dmg = 2;
-               if(autocvar_g_balance_nex_charge)
+               if(WEP_CVAR(vortex, charge))
                {
-                       if(autocvar_g_balance_nex_secondary_chargepool)
-                               self.nex_chargepool_ammo = 1;
-                       self.nex_charge = autocvar_g_balance_nex_charge_start;
+                       if(WEP_CVAR_SEC(vortex, chargepool))
+                               self.vortex_chargepool_ammo = 1;
+                       self.vortex_charge = WEP_CVAR(vortex, charge_start);
                }
 
                if(warmup_stage)
@@ -432,6 +507,7 @@ void PutClientInServer (void)
                        self.ammo_nails = warmup_start_ammo_nails;
                        self.ammo_rockets = warmup_start_ammo_rockets;
                        self.ammo_cells = warmup_start_ammo_cells;
+                       self.ammo_plasma = warmup_start_ammo_plasma;
                        self.ammo_fuel = warmup_start_ammo_fuel;
                        self.health = warmup_start_health;
                        self.armorvalue = warmup_start_armorvalue;
@@ -443,6 +519,7 @@ void PutClientInServer (void)
                        self.ammo_nails = start_ammo_nails;
                        self.ammo_rockets = start_ammo_rockets;
                        self.ammo_cells = start_ammo_cells;
+                       self.ammo_plasma = start_ammo_plasma;
                        self.ammo_fuel = start_ammo_fuel;
                        self.health = start_health;
                        self.armorvalue = start_armorvalue;
@@ -454,13 +531,13 @@ void PutClientInServer (void)
                else
                        self.superweapons_finished = 0;
 
-               if(g_weaponarena_random)
+               if(g_weaponarena_random) // WEAPONTODO: more stuff that should be in a mutator. also: rename those cvars
                {
-                       if(g_weaponarena_random_with_laser)
-                               self.weapons &= ~WEPSET_LASER;
+                       if(g_weaponarena_random_with_blaster)
+                               self.weapons &= ~WEPSET_BLASTER;
                        W_RandomWeapons(self, g_weaponarena_random);
-                       if(g_weaponarena_random_with_laser)
-                               self.weapons |= WEPSET_LASER;
+                       if(g_weaponarena_random_with_blaster)
+                               self.weapons |= WEPSET_BLASTER;
                }
 
                self.items = start_items;
@@ -505,7 +582,7 @@ void PutClientInServer (void)
                self.angles_z = 0; // never spawn tilted even if the spot says to
                if(IS_BOT_CLIENT(self))
                        self.v_angle = self.angles;
-               self.fixangle = TRUE; // turn this way immediately
+               self.fixangle = true; // turn this way immediately
                self.velocity = '0 0 0';
                self.avelocity = '0 0 0';
                self.punchangle = '0 0 0';
@@ -516,7 +593,7 @@ void PutClientInServer (void)
 
                entity spawnevent = spawn();
                spawnevent.owner = self;
-               Net_LinkEntity(spawnevent, FALSE, 0.5, SpawnEvent_Send);
+               Net_LinkEntity(spawnevent, false, 0.5, SpawnEvent_Send);
 
                // Cut off any still running player sounds.
                stopsound(self, CH_PLAYER_SINGLE);
@@ -525,11 +602,11 @@ void PutClientInServer (void)
                FixPlayermodel();
                self.drawonlytoclient = world;
 
-               self.crouch = FALSE;
+               self.crouch = false;
                self.view_ofs = PL_VIEW_OFS;
                setsize (self, PL_MIN, PL_MAX);
                self.spawnorigin = spot.origin;
-               setorigin (self, spot.origin + '0 0 1' * (1 - self.mins_z - 24));
+               setorigin (self, spot.origin + '0 0 1' * (1 - self.mins.z - 24));
                // don't reset back to last position, even if new position is stuck in solid
                self.oldorigin = self.origin;
                self.prevorigin = self.origin;
@@ -539,12 +616,11 @@ void PutClientInServer (void)
 
                self.event_damage = PlayerDamage;
 
-               self.bot_attack = TRUE;
-               self.monster_attack = TRUE;
-               
+               self.bot_attack = true;
+               self.monster_attack = true;
+
                self.spider_slowness = 0;
 
-               self.statdraintime = time + 5;
                self.BUTTON_ATCK = self.BUTTON_JUMP = self.BUTTON_ATCK2 = 0;
 
                if(self.killcount == -666) {
@@ -557,7 +633,7 @@ void PutClientInServer (void)
                self.colormod = '1 1 1' * autocvar_g_player_brightness;
                self.exteriorweaponentity.alpha = default_weapon_alpha;
 
-               self.speedrunning = FALSE;
+               self.speedrunning = false;
 
                //stuffcmd(self, "chase_active 0");
                //stuffcmd(self, "set viewsize $tmpviewsize \n");
@@ -567,13 +643,12 @@ void PutClientInServer (void)
                // reset fields the weapons may use
                for (j = WEP_FIRST; j <= WEP_LAST; ++j)
                {
-                       weapon_action(j, WR_RESETPLAYER);
+                       WEP_ACTION(j, WR_RESETPLAYER);
 
                        // all weapons must be fully loaded when we spawn
-                       entity e;
-                       e = get_weaponinfo(j);
+                       entity e = get_weaponinfo(j);
                        if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
-                               self.(weapon_load[j]) = cvar(strcat("g_balance_", e.netname, "_reload_ammo"));
+                               self.(weapon_load[j]) = e.reloading_ammo;
                }
 
                oldself = self;
@@ -627,31 +702,28 @@ float ClientInit_SendEntity(entity to, float sf)
        WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[1]));
        WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[2]));
        WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[3]));
-       WriteInt24_t(MSG_ENTITY, compressShotOrigin(electro_shotorigin[0]));
-       WriteInt24_t(MSG_ENTITY, compressShotOrigin(electro_shotorigin[1]));
-       WriteInt24_t(MSG_ENTITY, compressShotOrigin(electro_shotorigin[2]));
-       WriteInt24_t(MSG_ENTITY, compressShotOrigin(electro_shotorigin[3]));
-       WriteInt24_t(MSG_ENTITY, compressShotOrigin(gauntlet_shotorigin[0]));
-       WriteInt24_t(MSG_ENTITY, compressShotOrigin(gauntlet_shotorigin[1]));
-       WriteInt24_t(MSG_ENTITY, compressShotOrigin(gauntlet_shotorigin[2]));
-       WriteInt24_t(MSG_ENTITY, compressShotOrigin(gauntlet_shotorigin[3]));
+       WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[0]));
+       WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[1]));
+       WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[2]));
+       WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[3]));
+
        if(sv_foginterval && world.fog != "")
                WriteString(MSG_ENTITY, world.fog);
        else
                WriteString(MSG_ENTITY, "");
        WriteByte(MSG_ENTITY, self.count * 255.0); // g_balance_armor_blockpercent
-       WriteCoord(MSG_ENTITY, self.bouncefactor); // g_balance_grenadelauncher_bouncefactor
-       WriteCoord(MSG_ENTITY, self.bouncestop); // g_balance_grenadelauncher_bouncestop
-       WriteCoord(MSG_ENTITY, self.ebouncefactor); // g_balance_grenadelauncher_bouncefactor
-       WriteCoord(MSG_ENTITY, self.ebouncestop); // g_balance_grenadelauncher_bouncestop
-       WriteByte(MSG_ENTITY, autocvar_g_balance_nex_secondary); // client has to know if it should zoom or not
-       WriteByte(MSG_ENTITY, autocvar_g_balance_rifle_secondary); // client has to know if it should zoom or not
+       WriteCoord(MSG_ENTITY, self.bouncefactor); // g_balance_mortar_bouncefactor // WEAPONTODO
+       WriteCoord(MSG_ENTITY, self.bouncestop); // g_balance_mortar_bouncestop
+       WriteCoord(MSG_ENTITY, self.ebouncefactor); // g_balance_mortar_bouncefactor
+       WriteCoord(MSG_ENTITY, self.ebouncestop); // g_balance_mortar_bouncestop
+       WriteByte(MSG_ENTITY, WEP_CVAR(vortex, secondary)); // client has to know if it should zoom or not // WEAPONTODO
+       WriteByte(MSG_ENTITY, WEP_CVAR(rifle, secondary)); // client has to know if it should zoom or not // WEAPONTODO
        WriteByte(MSG_ENTITY, serverflags); // client has to know if it should zoom or not
-       WriteByte(MSG_ENTITY, autocvar_g_balance_minelayer_limit); // minelayer max mines
-       WriteByte(MSG_ENTITY, autocvar_g_balance_hagar_secondary_load_max); // hagar max loadable rockets
+       WriteByte(MSG_ENTITY, WEP_CVAR(minelayer, limit)); // minelayer max mines // WEAPONTODO
+       WriteByte(MSG_ENTITY, WEP_CVAR_SEC(hagar, load_max)); // hagar max loadable rockets // WEAPONTODO
        WriteCoord(MSG_ENTITY, autocvar_g_trueaim_minrange);
-       WriteByte(MSG_ENTITY, autocvar_g_balance_porto_secondary);
-       return TRUE;
+       WriteByte(MSG_ENTITY, WEP_CVAR(porto, secondary)); // WEAPONTODO
+       return true;
 }
 
 void ClientInit_CheckUpdate()
@@ -662,14 +734,14 @@ void ClientInit_CheckUpdate()
                self.count = autocvar_g_balance_armor_blockpercent;
                self.SendFlags |= 1;
        }
-       if(self.bouncefactor != autocvar_g_balance_grenadelauncher_bouncefactor)
+       if(self.bouncefactor != autocvar_g_balance_mortar_bouncefactor) // WEAPONTODO
        {
-               self.bouncefactor = autocvar_g_balance_grenadelauncher_bouncefactor;
+               self.bouncefactor = autocvar_g_balance_mortar_bouncefactor;
                self.SendFlags |= 1;
        }
-       if(self.bouncestop != autocvar_g_balance_grenadelauncher_bouncestop)
+       if(self.bouncestop != autocvar_g_balance_mortar_bouncestop)
        {
-               self.bouncestop = autocvar_g_balance_grenadelauncher_bouncestop;
+               self.bouncestop = autocvar_g_balance_mortar_bouncestop;
                self.SendFlags |= 1;
        }
        if(self.ebouncefactor != autocvar_g_balance_electro_secondary_bouncefactor)
@@ -691,7 +763,7 @@ void ClientInit_Spawn()
        e = spawn();
        e.classname = "clientinit";
        e.think = ClientInit_CheckUpdate;
-       Net_LinkEntity(e, FALSE, 0, ClientInit_SendEntity);
+       Net_LinkEntity(e, false, 0, ClientInit_SendEntity);
 
        o = self;
        self = e;
@@ -750,7 +822,7 @@ void ClientKill_Now_TeamChange()
 {
        if(self.killindicator_teamchange == -1)
        {
-               JoinBestTeam( self, FALSE, TRUE );
+               JoinBestTeam( self, false, true );
        }
        else if(self.killindicator_teamchange == -2)
        {
@@ -783,8 +855,8 @@ void ClientKill_Now()
        if(self.killindicator_teamchange)
                ClientKill_Now_TeamChange();
 
-       // in any case:
-       Damage(self, self, self, 100000, DEATH_KILL, self.origin, '0 0 0');
+       if(IS_PLAYER(self))
+               Damage(self, self, self, 100000, DEATH_KILL, self.origin, '0 0 0');
 
        // now I am sure the player IS dead
 }
@@ -964,23 +1036,6 @@ void FixClientCvars(entity e)
                stuffcmd(e, "cl_cmd settemp cl_prydoncursor_notrace 0\n");
        if(autocvar_sv_gentle)
                stuffcmd(e, "cl_cmd settemp cl_gentle 1\n");
-       /*
-        * we no longer need to stuff this. Remove this comment block if you feel
-        * 2.3 and higher (or was it 2.2.3?) don't need these any more
-       stuffcmd(e, strcat("cl_gravity ", ftos(autocvar_sv_gravity), "\n"));
-       stuffcmd(e, strcat("cl_movement_accelerate ", ftos(autocvar_sv_accelerate), "\n"));
-       stuffcmd(e, strcat("cl_movement_friction ", ftos(autocvar_sv_friction), "\n"));
-       stuffcmd(e, strcat("cl_movement_maxspeed ", ftos(autocvar_sv_maxspeed), "\n"));
-       stuffcmd(e, strcat("cl_movement_airaccelerate ", ftos(autocvar_sv_airaccelerate), "\n"));
-       stuffcmd(e, strcat("cl_movement_maxairspeed ", ftos(autocvar_sv_maxairspeed), "\n"));
-       stuffcmd(e, strcat("cl_movement_stopspeed ", ftos(autocvar_sv_stopspeed), "\n"));
-       stuffcmd(e, strcat("cl_movement_jumpvelocity ", ftos(autocvar_sv_jumpvelocity), "\n"));
-       stuffcmd(e, strcat("cl_movement_stepheight ", ftos(autocvar_sv_stepheight), "\n"));
-       stuffcmd(e, strcat("set cl_movement_friction_on_land ", ftos(autocvar_sv_friction_on_land), "\n"));
-       stuffcmd(e, strcat("set cl_movement_airaccel_qw ", ftos(autocvar_sv_airaccel_qw), "\n"));
-       stuffcmd(e, strcat("set cl_movement_airaccel_sideways_friction ", ftos(autocvar_sv_airaccel_sideways_friction), "\n"));
-       stuffcmd(e, "cl_movement_edgefriction 1\n");
-        */
 }
 
 float PlayerInIDList(entity p, string idlist)
@@ -988,7 +1043,7 @@ float PlayerInIDList(entity p, string idlist)
        float n, i;
        string s;
 
-       // NOTE: we do NOT check crypto_keyfp here, an unsigned ID is fine too for this
+       // NOTE: we do NOT check crypto_idfp_signed here, an unsigned ID is fine too for this
        if (!p.crypto_idfp)
                return 0;
 
@@ -1004,6 +1059,27 @@ float PlayerInIDList(entity p, string idlist)
        return 0;
 }
 
+#ifdef DP_EXT_PRECONNECT
+/*
+=============
+ClientPreConnect
+
+Called once (not at each match start) when a client begins a connection to the server
+=============
+*/
+void ClientPreConnect (void)
+{
+       if(autocvar_sv_eventlog)
+       {
+               GameLogEcho(sprintf(":connect:%d:%d:%s",
+                       self.playerid,
+                       num_for_edict(self),
+                       ((IS_REAL_CLIENT(self)) ? self.netaddress : "bot")
+               ));
+       }
+}
+#endif
+
 /*
 =============
 ClientConnect
@@ -1044,6 +1120,8 @@ void ClientConnect (void)
                player_count = 0;
        }
 
+       if(IS_REAL_CLIENT(self)) { PlayerStats_PlayerBasic_CheckUpdate(self); }
+
        PlayerScore_Attach(self);
        ClientData_Attach();
        accuracy_init(self);
@@ -1096,7 +1174,7 @@ void ClientConnect (void)
                if(self.team_forced > 0)
                        self.team_forced = 0;
 
-       JoinBestTeam(self, FALSE, FALSE); // if the team number is valid, keep it
+       JoinBestTeam(self, false, false); // if the team number is valid, keep it
 
        if((autocvar_sv_spectate == 1) || autocvar_g_campaign || self.team_forced < 0) {
                self.classname = "observer";
@@ -1122,17 +1200,17 @@ void ClientConnect (void)
 
        self.playerid = (playerid_last = playerid_last + 1);
 
-       PlayerStats_AddEvent(sprintf("kills-%d", self.playerid));
+       PlayerStats_GameReport_AddEvent(sprintf("kills-%d", self.playerid));
 
     if(IS_BOT_CLIENT(self))
-        PlayerStats_AddPlayer(self);
+        PlayerStats_GameReport_AddPlayer(self);
 
        if(autocvar_sv_eventlog)
                GameLogEcho(strcat(":join:", ftos(self.playerid), ":", ftos(num_for_edict(self)), ":", ((IS_REAL_CLIENT(self)) ? self.netaddress : "bot"), ":", self.netname));
 
        LogTeamchange(self.playerid, self.team, 1);
 
-       self.just_joined = TRUE;  // stop spamming the eventlog with additional lines when the client connects
+       self.just_joined = true;  // stop spamming the eventlog with additional lines when the client connects
 
        self.netname_previous = strzone(self.netname);
 
@@ -1152,6 +1230,10 @@ void ClientConnect (void)
        // Wazat's grappling hook
        SetGrappleHookBindings();
 
+       // Jetpack binds
+       stuffcmd(self, "alias +jetpack +button10\n");
+       stuffcmd(self, "alias -jetpack -button10\n");
+
        // get version info from player
        stuffcmd(self, "cmd clientversion $gameversion\n");
 
@@ -1196,13 +1278,7 @@ void ClientConnect (void)
        if(!sv_foginterval && world.fog != "")
                stuffcmd(self, strcat("\nfog ", world.fog, "\nr_fog_exp2 0\nr_drawfog 1\n"));
 
-       if(autocvar_g_hitplots || strstrofs(strcat(" ", autocvar_g_hitplots_individuals, " "), strcat(" ", self.netaddress, " "), 0) >= 0)
-       {
-               self.hitplotfh = fopen(strcat("hits-", matchid, "-", self.netaddress, "-", ftos(self.playerid), ".plot"), FILE_WRITE);
-               fputs(self.hitplotfh, strcat("#name ", self.netname, "\n"));
-       }
-       else
-               self.hitplotfh = -1;
+       W_HitPlotOpen(self);
 
        if(autocvar_sv_teamnagger && !(autocvar_bot_vs_human && (c3==-1 && c4==-1)) && !g_ca && !g_cts && !g_race) // teamnagger is currently bad for ca, race & cts
                send_CSQC_teamnagger();
@@ -1216,6 +1292,13 @@ void ClientConnect (void)
        if(IS_REAL_CLIENT(self))
                sv_notice_join();
 
+       for (entity e = world; (e = findfloat(e, init_for_player_needed, 1)); ) {
+               entity oldself = self;
+               self = e;
+               e.init_for_player(oldself);
+               self = oldself;
+       }
+
        MUTATOR_CALLHOOK(ClientConnect);
 }
 /*
@@ -1238,17 +1321,15 @@ void ClientDisconnect (void)
                return;
        }
 
-       if(IS_PLAYER(self)) { pointparticles(particleeffectnum("spawn_event_neutral"), self.origin, '0 0 0', 1); }
+       PlayerStats_GameReport_FinalizePlayer(self);
 
-       PlayerStats_AddGlobalInfo(self);
+       SetSpectator(self, world);
+
+       if(IS_PLAYER(self)) { pointparticles(particleeffectnum("spawn_event_neutral"), self.origin, '0 0 0', 1); }
 
        CheatShutdownClient();
 
-       if(self.hitplotfh >= 0)
-       {
-               fclose(self.hitplotfh);
-               self.hitplotfh = -1;
-       }
+       W_HitPlotClose(self);
 
        anticheat_report();
        anticheat_shutdown();
@@ -1345,7 +1426,7 @@ void UpdateChatBubble()
                self.chatbubbleentity.nextthink = time;
                setmodel(self.chatbubbleentity, "models/misc/chatbubble.spr"); // precision set below
                //setorigin(self.chatbubbleentity, self.origin + '0 0 15' + self.maxs_z * '0 0 1');
-               setorigin(self.chatbubbleentity, '0 0 15' + self.maxs_z * '0 0 1');
+               setorigin(self.chatbubbleentity, '0 0 15' + self.maxs.z * '0 0 1');
                setattachment(self.chatbubbleentity, self, "");  // sticks to moving player better, also conserves bandwidth
                self.chatbubbleentity.mdl = self.chatbubbleentity.model;
                self.chatbubbleentity.model = "";
@@ -1417,7 +1498,7 @@ void player_powerups (void)
        Fire_ApplyDamage(self);
        Fire_ApplyEffect(self);
 
-       if (!g_minstagib)
+       if (!g_instagib)
        {
                if (self.items & IT_STRENGTH)
                {
@@ -1580,7 +1661,7 @@ void player_regen (void)
                mina = autocvar_g_balance_armor_regenstable;
                limith = autocvar_g_balance_health_limit;
                limita = autocvar_g_balance_armor_limit;
-               
+
                max_mod = regen_mod_max;
                regen_mod = regen_mod_regen;
                rot_mod = regen_mod_rot;
@@ -1625,12 +1706,12 @@ void SetZoomState(float z)
 
 void GetPressedKeys(void) {
        MUTATOR_CALLHOOK(GetPressedKeys);
-       if (self.movement_x > 0) // get if movement keys are pressed
+       if (self.movement.x > 0) // get if movement keys are pressed
        {       // forward key pressed
                self.pressedkeys |= KEY_FORWARD;
                self.pressedkeys &= ~KEY_BACKWARD;
        }
-       else if (self.movement_x < 0)
+       else if (self.movement.x < 0)
        {       // backward key pressed
                self.pressedkeys |= KEY_BACKWARD;
                self.pressedkeys &= ~KEY_FORWARD;
@@ -1641,12 +1722,12 @@ void GetPressedKeys(void) {
                self.pressedkeys &= ~KEY_BACKWARD;
        }
 
-       if (self.movement_y > 0)
+       if (self.movement.y > 0)
        {       // right key pressed
                self.pressedkeys |= KEY_RIGHT;
                self.pressedkeys &= ~KEY_LEFT;
        }
-       else if (self.movement_y < 0)
+       else if (self.movement.y < 0)
        {       // left key pressed
                self.pressedkeys |= KEY_LEFT;
                self.pressedkeys &= ~KEY_RIGHT;
@@ -1688,6 +1769,7 @@ void SpectateCopy(entity spectatee) {
        self.armortype = spectatee.armortype;
        self.armorvalue = spectatee.armorvalue;
        self.ammo_cells = spectatee.ammo_cells;
+       self.ammo_plasma = spectatee.ammo_plasma;
        self.ammo_shells = spectatee.ammo_shells;
        self.ammo_nails = spectatee.ammo_nails;
        self.ammo_rockets = spectatee.ammo_rockets;
@@ -1708,9 +1790,10 @@ void SpectateCopy(entity spectatee) {
        self.switchweapon = spectatee.switchweapon;
        self.switchingweapon = spectatee.switchingweapon;
        self.weapon = spectatee.weapon;
-       self.nex_charge = spectatee.nex_charge;
-       self.nex_chargepool_ammo = spectatee.nex_chargepool_ammo;
+       self.vortex_charge = spectatee.vortex_charge;
+       self.vortex_chargepool_ammo = spectatee.vortex_chargepool_ammo;
        self.hagar_load = spectatee.hagar_load;
+       self.arc_heat_percent = spectatee.arc_heat_percent;
        self.minelayer_mines = spectatee.minelayer_mines;
        self.punchangle = spectatee.punchangle;
        self.view_ofs = spectatee.view_ofs;
@@ -1723,7 +1806,7 @@ void SpectateCopy(entity spectatee) {
        self.frozen = spectatee.frozen;
        self.revive_progress = spectatee.revive_progress;
        if(!self.BUTTON_USE)
-               self.fixangle = TRUE;
+               self.fixangle = true;
        setorigin(self, spectatee.origin);
        setsize(self, spectatee.mins, spectatee.maxs);
        SetZoomState(spectatee.zoomstate);
@@ -1732,7 +1815,7 @@ void SpectateCopy(entity spectatee) {
        self.hud = spectatee.hud;
        if(spectatee.vehicle)
     {
-        self.fixangle = FALSE;
+        self.fixangle = false;
         //self.velocity = spectatee.vehicle.velocity;
         self.vehicle_health = spectatee.vehicle_health;
         self.vehicle_shield = spectatee.vehicle_shield;
@@ -1745,9 +1828,9 @@ void SpectateCopy(entity spectatee) {
         msg_entity = self;
 
         WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
-            WriteAngle(MSG_ONE,  spectatee.v_angle_x);
-            WriteAngle(MSG_ONE,  spectatee.v_angle_y);
-            WriteAngle(MSG_ONE,  spectatee.v_angle_z);
+            WriteAngle(MSG_ONE,  spectatee.v_angle.x);
+            WriteAngle(MSG_ONE,  spectatee.v_angle.y);
+            WriteAngle(MSG_ONE,  spectatee.v_angle.z);
 
         //WriteByte (MSG_ONE, SVC_SETVIEW);
         //    WriteEntity(MSG_ONE, self);
@@ -1756,80 +1839,83 @@ void SpectateCopy(entity spectatee) {
     }
 }
 
-float SpectateUpdate() {
+float SpectateUpdate()
+{
        if(!self.enemy)
            return 0;
 
-       if (self == self.enemy)
-               return 0;
-
-       if (!IS_PLAYER(self.enemy))
+       if(!IS_PLAYER(self.enemy) || self == self.enemy)
+       {
+               SetSpectator(self, world);
                return 0;
+       }
 
        SpectateCopy(self.enemy);
 
        return 1;
 }
 
-
 float SpectateSet()
 {
-       if(self.enemy.classname != "player")
-               return FALSE;
-       /*if(self.enemy.vehicle)
-       {
+       if(!IS_PLAYER(self.enemy))
+               return false;
 
-               msg_entity = self;
-               WriteByte(MSG_ONE, SVC_SETVIEW);
-               WriteEntity(MSG_ONE, self.enemy);
-               //stuffcmd(self, "set viewsize $tmpviewsize \n");
+       ClientData_Touch(self.enemy);
 
-               self.movetype = MOVETYPE_NONE;
-               accuracy_resend(self);
-       }
-       else
-       {*/
-               msg_entity = self;
-               WriteByte(MSG_ONE, SVC_SETVIEW);
-               WriteEntity(MSG_ONE, self.enemy);
-               //stuffcmd(self, "set viewsize $tmpviewsize \n");
-               self.movetype = MOVETYPE_NONE;
-               accuracy_resend(self);
+       msg_entity = self;
+       WriteByte(MSG_ONE, SVC_SETVIEW);
+       WriteEntity(MSG_ONE, self.enemy);
+       //stuffcmd(self, "set viewsize $tmpviewsize \n");
+       self.movetype = MOVETYPE_NONE;
+       accuracy_resend(self);
 
-               if(!SpectateUpdate())
-                       PutObserverInServer();
-       //}
-       return TRUE;
+       if(!SpectateUpdate())
+               PutObserverInServer();
+
+       return true;
+}
+
+void SetSpectator(entity player, entity spectatee)
+{
+       entity old_spectatee = player.enemy;
+
+       player.enemy = spectatee;
+
+       // WEAPONTODO
+       // these are required to fix the spectator bug with arc
+       if(old_spectatee && old_spectatee.arc_beam) { old_spectatee.arc_beam.SendFlags |= ARC_SF_SETTINGS; }
+       if(player.enemy && player.enemy.arc_beam) { player.enemy.arc_beam.SendFlags |= ARC_SF_SETTINGS; }
+
+       // needed to update spectator list
+       if(old_spectatee) { ClientData_Touch(old_spectatee); }
 }
 
 float Spectate(entity pl)
 {
        if(g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer)
-       if(pl.team != self.team)
+       if(DIFF_TEAM(pl, self))
                return 0;
 
-       self.enemy = pl;
+       SetSpectator(self, pl);
        return SpectateSet();
 }
 
 // Returns next available player to spectate if g_ca_spectate_enemies == 0
-entity CA_SpectateNext(entity start) {
-       if (start.team == self.team) {
-               return start;
-       }
+entity CA_SpectateNext(entity start)
+{
+       if(SAME_TEAM(start, self)) { return start; }
 
        other = start;
        // continue from current player
-       while(other && other.team != self.team) {
+       while(other && DIFF_TEAM(other, self))
                other = find(other, classname, "player");
-       }
 
-       if (!other) {
+       if (!other)
+       {
                // restart from begining
                other = find(other, classname, "player");
-               while(other && other.team != self.team) {
+               while(other && DIFF_TEAM(other, self))
                        other = find(other, classname, "player");
-               }
        }
 
        return other;
@@ -1839,17 +1925,19 @@ float SpectateNext()
 {
        other = find(self.enemy, classname, "player");
 
-       if (g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer) {
+       if (g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer)
+       {
                // CA and ca players when spectating enemies is forbidden
                other = CA_SpectateNext(other);
-       } else {
+       }
+       else
+       {
                // other modes and ca spectators or spectating enemies is allowed
                if (!other)
                        other = find(other, classname, "player");
        }
 
-       if (other)
-               self.enemy = other;
+       if(other) { SetSpectator(self, other); }
 
        return SpectateSet();
 }
@@ -1859,7 +1947,7 @@ float SpectatePrev()
        // NOTE: chain order is from the highest to the lower entnum (unlike find)
        other = findchain(classname, "player");
        if (!other) // no player
-               return FALSE;
+               return false;
 
        entity first = other;
        // skip players until current spectated player
@@ -1878,7 +1966,7 @@ float SpectatePrev()
                        while(other.team != self.team)
                                other = other.chain;
                        if(other == self.enemy)
-                               return TRUE;
+                               return true;
                }
        }
        else
@@ -1888,7 +1976,7 @@ float SpectatePrev()
                else
                        other = first;
        }
-       self.enemy = other;
+       SetSpectator(self, other);
        return SpectateSet();
 }
 
@@ -1929,8 +2017,10 @@ void LeaveSpectatorMode()
                        self.classname = "player";
                        nades_RemoveBonus(self);
 
+                       SetSpectator(self, world);
+
                        if(autocvar_g_campaign || autocvar_g_balance_teams)
-                               { JoinBestTeam(self, FALSE, TRUE); }
+                               { JoinBestTeam(self, false, true); }
 
                        if(autocvar_g_campaign)
                                { campaign_bots_may_start = 1; }
@@ -1953,7 +2043,7 @@ void LeaveSpectatorMode()
 
 /**
  * Determines whether the player is allowed to join. This depends on cvar
- * g_maxplayers, if it isn't used this function always return TRUE, otherwise
+ * g_maxplayers, if it isn't used this function always return true, otherwise
  * it checks whether the number of currently playing players exceeds g_maxplayers.
  * @return int number of free slots for players, 0 if none
  */
@@ -1983,7 +2073,7 @@ float nJoinAllowed(entity ignore) {
 
        float currentlyPlaying = 0;
        FOR_EACH_REALCLIENT(e)
-               if(IS_PLAYER(e) || e.caplayer == 1)
+               if(IS_PLAYER(e) || e.caplayer)
                        currentlyPlaying += 1;
 
        if(currentlyPlaying < autocvar_g_maxplayers)
@@ -1997,7 +2087,10 @@ float nJoinAllowed(entity ignore) {
  * g_maxplayers_spectator_blocktime seconds
  */
 void checkSpectatorBlock() {
-       if(IS_SPEC(self) || IS_OBSERVER(self)) {
+       if(IS_SPEC(self) || IS_OBSERVER(self))
+       if(!self.caplayer)
+       if(IS_REAL_CLIENT(self))
+       {
                if( time > (self.spectatortime + autocvar_g_maxplayers_spectator_blocktime) ) {
                        Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_QUIT_KICK_SPECTATING);
                        dropclient(self);
@@ -2146,6 +2239,33 @@ void PlayerUseKey()
        MUTATOR_CALLHOOK(PlayerUseKey);
 }
 
+float isInvisibleString(string s)
+{
+       float i, n, c;
+       s = strdecolorize(s);
+       for((i = 0), (n = strlen(s)); i < n; ++i)
+       {
+               c = str2chr(s, i);
+               switch(c)
+               {
+                       case 0:
+                       case 32: // space
+                               break;
+                       case 192: // charmap space
+                               if (!autocvar_utf8_enable)
+                                       break;
+                               return false;
+                       case 160: // space in unicode fonts
+                       case 0xE000 + 192: // utf8 charmap space
+                               if (autocvar_utf8_enable)
+                                       break;
+                       default:
+                               return false;
+               }
+       }
+       return true;
+}
+
 /*
 =============
 PlayerPreThink
@@ -2155,14 +2275,14 @@ Called every frame for each client before the physics are run
 */
 .float usekeypressed;
 void() nexball_setstatus;
-.float items_added;
+.int items_added;
 void PlayerPreThink (void)
 {
        WarpZone_PlayerPhysics_FixVAngle();
 
        self.stat_game_starttime = game_starttime;
        self.stat_round_starttime = round_starttime;
-       self.stat_allow_oldnexbeam = autocvar_g_allow_oldnexbeam;
+       self.stat_allow_oldvortexbeam = autocvar_g_allow_oldvortexbeam;
        self.stat_leadlimit = autocvar_leadlimit;
 
        if(frametime)
@@ -2177,8 +2297,17 @@ void PlayerPreThink (void)
 
        zoomstate_set = 0;
 
-       if(self.netname_previous != self.netname)
-       {
+       // Savage: Check for nameless players
+       if (isInvisibleString(self.netname)) {
+               string new_name = strzone(strcat("Player@", ftos(self.playerid)));
+               if(autocvar_sv_eventlog)
+                       GameLogEcho(strcat(":name:", ftos(self.playerid), ":", new_name));
+               if(self.netname_previous)
+                       strunzone(self.netname_previous);
+               self.netname_previous = strzone(new_name);
+               self.netname = self.netname_previous;
+               // stuffcmd(self, strcat("name ", self.netname, "\n"));
+       } else if(self.netname_previous != self.netname) {
                if(autocvar_sv_eventlog)
                        GameLogEcho(strcat(":name:", ftos(self.playerid), ":", self.netname));
                if(self.netname_previous)
@@ -2246,7 +2375,7 @@ void PlayerPreThink (void)
        {
                self.revive_progress = bound(0, self.revive_progress - frametime * self.revive_speed, 1);
                self.health = max(0, autocvar_g_nades_ice_health + (start_health-autocvar_g_nades_ice_health) * self.revive_progress );
-               
+
                if(self.health < 1)
                {
                        if(self.vehicle)
@@ -2285,26 +2414,26 @@ void PlayerPreThink (void)
                        // FIXME turn this into CSQC stuff
                        self.v_angle = self.lastV_angle;
                        self.angles = self.lastV_angle;
-                       self.fixangle = TRUE;
+                       self.fixangle = true;
                }
 
                if(frametime)
                {
-                       if(self.weapon == WEP_NEX && autocvar_g_balance_nex_charge)
+                       if(self.weapon == WEP_VORTEX && WEP_CVAR(vortex, charge))
                        {
-                               self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit);
-                               self.weaponentity_glowmod_y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit);
-                               self.weaponentity_glowmod_z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit);
+                               self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
+                               self.weaponentity_glowmod_y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
+                               self.weaponentity_glowmod_z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
 
-                               if(self.nex_charge > autocvar_g_balance_nex_charge_animlimit)
+                               if(self.vortex_charge > WEP_CVAR(vortex, charge_animlimit))
                                {
-                                       self.weaponentity_glowmod_x = self.weaponentity_glowmod_x + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit);
-                                       self.weaponentity_glowmod_y = self.weaponentity_glowmod_y + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit);
-                                       self.weaponentity_glowmod_z = self.weaponentity_glowmod_z + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit);
+                                       self.weaponentity_glowmod_x = self.weaponentity_glowmod.x + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
+                                       self.weaponentity_glowmod_y = self.weaponentity_glowmod.y + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
+                                       self.weaponentity_glowmod_z = self.weaponentity_glowmod.z + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
                                }
                        }
                        else
-                               self.weaponentity_glowmod = colormapPaletteColor(self.clientcolors & 0x0F, TRUE) * 2;
+                               self.weaponentity_glowmod = colormapPaletteColor(self.clientcolors & 0x0F, true) * 2;
 
                        player_powerups();
                }
@@ -2383,27 +2512,30 @@ void PlayerPreThink (void)
                        do_crouch = 0;
                if(self.frozen)
                        do_crouch = 0;
-               if(self.weapon == WEP_SHOTGUN && self.weaponentity.wframe == WFRAME_FIRE2 && time < self.weapon_nextthink)
+
+               // WEAPONTODO: THIS SHIT NEEDS TO GO EVENTUALLY
+               // It cannot be predicted by the engine!
+               if((self.weapon == WEP_SHOCKWAVE || self.weapon == WEP_SHOTGUN) && self.weaponentity.wframe == WFRAME_FIRE2 && time < self.weapon_nextthink)
                        do_crouch = 0;
 
                if (do_crouch)
                {
                        if (!self.crouch)
                        {
-                               self.crouch = TRUE;
+                               self.crouch = true;
                                self.view_ofs = PL_CROUCH_VIEW_OFS;
                                setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX);
-                               // setanim(self, self.anim_duck, FALSE, TRUE, TRUE); // this anim is BROKEN anyway
+                               // setanim(self, self.anim_duck, false, true, true); // this anim is BROKEN anyway
                        }
                }
                else
                {
                        if (self.crouch)
                        {
-                               tracebox(self.origin, PL_MIN, PL_MAX, self.origin, FALSE, self);
+                               tracebox(self.origin, PL_MIN, PL_MAX, self.origin, false, self);
                                if (!trace_startsolid)
                                {
-                                       self.crouch = FALSE;
+                                       self.crouch = false;
                                        self.view_ofs = PL_VIEW_OFS;
                                        setsize (self, PL_MIN, PL_MAX);
                                }
@@ -2431,9 +2563,10 @@ void PlayerPreThink (void)
 
                player_regen();
 
-               // rot nex charge to the charge limit
-               if(autocvar_g_balance_nex_charge_rot_rate && self.nex_charge > autocvar_g_balance_nex_charge_limit && self.nex_charge_rottime < time)
-                       self.nex_charge = bound(autocvar_g_balance_nex_charge_limit, self.nex_charge - autocvar_g_balance_nex_charge_rot_rate * frametime / W_TICSPERFRAME, 1);
+               // WEAPONTODO: Add a weapon request for this
+               // rot vortex charge to the charge limit
+               if(WEP_CVAR(vortex, charge_rot_rate) && self.vortex_charge > WEP_CVAR(vortex, charge_limit) && self.vortex_charge_rottime < time)
+                       self.vortex_charge = bound(WEP_CVAR(vortex, charge_limit), self.vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1);
 
                if(frametime)
                        player_anim();
@@ -2457,8 +2590,9 @@ void PlayerPreThink (void)
                SpectatorThink();
        }
 
+       // WEAPONTODO: Add weapon request for this
        if(!zoomstate_set)
-               SetZoomState(self.BUTTON_ZOOM || self.BUTTON_ZOOMSCRIPT || (self.BUTTON_ATCK2 && self.weapon == WEP_NEX) || (self.BUTTON_ATCK2 && self.weapon == WEP_RIFLE && autocvar_g_balance_rifle_secondary == 0));
+               SetZoomState(self.BUTTON_ZOOM || self.BUTTON_ZOOMSCRIPT || (self.BUTTON_ATCK2 && self.weapon == WEP_VORTEX) || (self.BUTTON_ATCK2 && self.weapon == WEP_RIFLE && WEP_CVAR(rifle, secondary) == 0)); // WEAPONTODO
 
        float oldspectatee_status;
        oldspectatee_status = self.spectatee_status;
@@ -2498,38 +2632,12 @@ void PlayerPreThink (void)
 
        target_voicescript_next(self);
 
+       // 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(!self.weapon)
                self.clip_load = self.clip_size = 0;
 }
 
-float isInvisibleString(string s)
-{
-       float i, n, c;
-       s = strdecolorize(s);
-       for((i = 0), (n = strlen(s)); i < n; ++i)
-       {
-               c = str2chr(s, i);
-               switch(c)
-               {
-                       case 0:
-                       case 32: // space
-                               break;
-                       case 192: // charmap space
-                               if (!autocvar_utf8_enable)
-                                       break;
-                               return FALSE;
-                       case 160: // space in unicode fonts
-                       case 0xE000 + 192: // utf8 charmap space
-                               if (autocvar_utf8_enable)
-                                       break;
-                       default:
-                               return FALSE;
-               }
-       }
-       return TRUE;
-}
-
 /*
 =============
 PlayerPostThink
@@ -2540,12 +2648,6 @@ Called every frame for each client after the physics are run
 .float idlekick_lasttimeleft;
 void PlayerPostThink (void)
 {
-       // Savage: Check for nameless players
-       if (isInvisibleString(self.netname)) {
-               self.netname = "Player";
-               stuffcmd(self, strcat("name ", self.netname, substring(ftos(random()), 2, -1), "\n"));
-       }
-
        if(sv_maxidle > 0 && frametime) // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).
        if(IS_PLAYER(self) || sv_maxidle_spectatorsareidle)
        {
@@ -2622,8 +2724,6 @@ void PlayerPostThink (void)
        }
        */
 
-       //pointparticles(particleeffectnum("machinegun_impact"), self.origin + self.view_ofs + '0 0 7', '0 0 0', 1);
-
        if(self.waypointsprite_attachedforcarrier)
                WaypointSprite_UpdateHealth(self.waypointsprite_attachedforcarrier, '1 0 0' * healtharmor_maxdamage(self.health, self.armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON));