]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/cl_player.qc
Merge branch 'master' into mirceakitsune/damage_effects
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / cl_player.qc
index b76e9a693471711b078c2690aaad753671ef1782..235fa72cd0b8da94d4d84291d234d15a110c4b09 100644 (file)
@@ -2,69 +2,53 @@ float weaponstats_buffer;
 
 void WeaponStats_Init()
 {
-       if(cvar_string("sv_weaponstats_killfile") != "" || cvar_string("sv_weaponstats_damagefile") != "")
+       if(autocvar_sv_weaponstats_file != "")
                weaponstats_buffer = buf_create();
        else
                weaponstats_buffer = -1;
 }
 
-#define WEAPONSTATS_GETINDEX(awep,vwep) ((vwep) + (awep) * (WEP_LAST - WEP_FIRST + 1) - (WEP_FIRST + WEP_FIRST * (WEP_LAST - WEP_FIRST + 1)))
+#define WEAPONSTATS_GETINDEX(awep,abot,vwep,vbot) (((vwep) + (awep) * (WEP_LAST - WEP_FIRST + 1) - (WEP_FIRST + WEP_FIRST * (WEP_LAST - WEP_FIRST + 1))) * 4 + (abot) * 2 + (vbot))
 
 void WeaponStats_Shutdown()
 {
-       float i, j, idx, f;
+       float i, j, ibot, jbot, idx;
        float fh;
+       vector v;
        string prefix;
        if(weaponstats_buffer < 0)
                return;
-       prefix = strcat(cvar_string("hostname"), "\t", GetGametype(), "_", GetMapname(), "\t");
-       if(cvar_string("sv_weaponstats_killfile") != "")
+       prefix = strcat(autocvar_hostname, "\t", GetGametype(), "_", GetMapname(), "\t");
+       if(autocvar_sv_weaponstats_file != "")
        {
-               fh = fopen(cvar_string("sv_weaponstats_killfile"), FILE_APPEND);
+               fh = fopen(autocvar_sv_weaponstats_file, FILE_APPEND);
                if(fh >= 0)
                {
-                       fputs(fh, "#begin killfile\n");
+                       fputs(fh, "#begin statsfile\n");
                        fputs(fh, strcat("#date ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"), "\n"));
                        fputs(fh, strcat("#config ", ftos(crc16(FALSE, cvar_changes)), "\n"));
-                       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-                               for(j = WEP_FIRST; j <= WEP_LAST; ++j)
+                       for(i = WEP_FIRST; i <= WEP_LAST; ++i) for(ibot = 0; ibot <= 1; ++ibot)
+                               for(j = WEP_FIRST; j <= WEP_LAST; ++j) for(jbot = 0; jbot <= 1; ++jbot)
                                {
-                                       idx = WEAPONSTATS_GETINDEX(i, j);
-                                       f = stov(bufstr_get(weaponstats_buffer, idx)) * '0 1 0';
-                                       if(f != 0)
-                                               fputs(fh, strcat(prefix, ftos(i), "\t", ftos(j), "\t", ftos(f), "\n"));
-                               }
-                       fputs(fh, "#end\n\n");
-                       fclose(fh);
-                       print("Weapon kill stats written\n");
-               }
-       }
-       if(cvar_string("sv_weaponstats_damagefile") != "")
-       {
-               fh = fopen(cvar_string("sv_weaponstats_damagefile"), FILE_APPEND);
-               if(fh >= 0)
-               {
-                       fputs(fh, "#begin damagefile\n");
-                       fputs(fh, strcat("#date ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"), "\n"));
-                       fputs(fh, strcat("#config ", ftos(crc16(FALSE, cvar_changes)), "\n"));
-                       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-                               for(j = WEP_FIRST; j <= WEP_LAST; ++j)
-                               {
-                                       idx = WEAPONSTATS_GETINDEX(i, j);
-                                       f = stov(bufstr_get(weaponstats_buffer, idx)) * '1 0 0';
-                                       if(f != 0)
-                                               fputs(fh, strcat(prefix, ftos(i), "\t", ftos(j), "\t", ftos(f), "\n"));
+                                       idx = WEAPONSTATS_GETINDEX(i, ibot, j, jbot);
+                                       v = stov(bufstr_get(weaponstats_buffer, idx));
+                                       if(v != '0 0 0')
+                                       {
+                                               //vector is: kills hits damage
+                                               fputs(fh, sprintf("%s%d %d\t%d %d\t", prefix, i, ibot, j, jbot));
+                                               fputs(fh, sprintf("%d %d %g\n", v_x, v_y, v_z));
+                                       }
                                }
                        fputs(fh, "#end\n\n");
                        fclose(fh);
-                       print("Weapon damage stats written\n");
+                       print("Weapon stats written\n");
                }
        }
        buf_del(weaponstats_buffer);
        weaponstats_buffer = -1;
 }
 
-void WeaponStats_LogItem(float awep, float vwep, vector item)
+void WeaponStats_LogItem(float awep, float abot, float vwep, float vbot, vector item)
 {
        float idx;
        if(weaponstats_buffer < 0)
@@ -73,18 +57,18 @@ void WeaponStats_LogItem(float awep, float vwep, vector item)
                return;
        if(awep > WEP_LAST || vwep > WEP_LAST)
                return;
-       idx = WEAPONSTATS_GETINDEX(awep,vwep);
+       idx = WEAPONSTATS_GETINDEX(awep,abot,vwep,vbot);
        bufstr_set(weaponstats_buffer, idx, vtos(stov(bufstr_get(weaponstats_buffer, idx)) + item));
 }
-void WeaponStats_LogDamage(float awep, float vwep, float damage)
+void WeaponStats_LogDamage(float awep, float abot, float vwep, float vbot, float damage)
 {
        if(damage < 0)
                error("negative damage?");
-       WeaponStats_LogItem(awep, vwep, '1 0 0' * damage);
+       WeaponStats_LogItem(awep, abot, vwep, vbot, '0 0 1' * damage + '0 1 0');
 }
-void WeaponStats_LogKill(float awep, float vwep)
+void WeaponStats_LogKill(float awep, float abot, float vwep, float vbot)
 {
-       WeaponStats_LogItem(awep, vwep, '0 1 0');
+       WeaponStats_LogItem(awep, abot, vwep, vbot, '1 0 0');
 }
 
 // changes by LordHavoc on 03/29/04 and 03/30/04 at Vermeulen's request
@@ -162,13 +146,16 @@ void CopyBody(float keepvelocity)
 
        Drag_MoveDrag(oldself, self);
 
+       Violence_DamageEffect_Copy(oldself, self);
+
+       self.owner = oldself;
        self = oldself;
 }
 
 float player_getspecies()
 {
        float s;
-       get_model_parameters(self.playermodel, self.skinindex);
+       get_model_parameters(self.model, self.skinindex);
        s = get_model_parameters_species;
        get_model_parameters(string_null, 0);
        if(s < 0)
@@ -204,6 +191,7 @@ void player_setupanimsformodel()
        self.anim_forwardleft = '20 1 1';
        self.anim_backright = '21 1 1';
        self.anim_backleft  = '22 1 1';
+       self.anim_melee = '23 1 1';
        animparseerror = FALSE;
        animfilename = strcat(self.model, ".animinfo");
        animfile = fopen(animfilename, FILE_READ);
@@ -230,6 +218,7 @@ void player_setupanimsformodel()
                self.anim_forwardleft  = animparseline(animfile);
                self.anim_backright    = animparseline(animfile);
                self.anim_backleft     = animparseline(animfile);
+               self.anim_melee        = animparseline(animfile);
                fclose(animfile);
 
                // derived anims
@@ -325,11 +314,14 @@ void SpawnThrownWeapon (vector org, float w)
                {
                        if(self.weapons & W_WeaponBit(j))
                                if(W_IsWeaponThrowable(j))
-                                       W_ThrowNewWeapon(self, j, FALSE, self.origin, randomvec() * 175 + '0 0 325');
+                                       W_ThrowNewWeapon(self, j, FALSE, org, randomvec() * 175 + '0 0 325');
                }
        }
        else
-               W_ThrowWeapon(randomvec() * 125 + '0 0 200', org - self.origin, FALSE);
+       {
+               if(W_IsWeaponThrowable(self.weapon))
+                       W_ThrowNewWeapon(self, self.weapon, FALSE, org, randomvec() * 125 + '0 0 200');
+       }
 }
 
 void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
@@ -341,7 +333,7 @@ void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float
        // damage resistance (ignore most of the damage from a bullet or similar)
        damage = max(damage - 5, 1);
 
-       v = healtharmor_applydamage(self.armorvalue, cvar("g_balance_armor_blockpercent"), damage);
+       v = healtharmor_applydamage(self.armorvalue, autocvar_g_balance_armor_blockpercent, damage);
        take = v_x;
        save = v_y;
 
@@ -365,13 +357,13 @@ void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float
                self.armorvalue = self.armorvalue - save;
                self.health = self.health - take;
                // pause regeneration for 5 seconds
-               self.pauseregen_finished = max(self.pauseregen_finished, time + cvar("g_balance_pause_health_regen"));
+               self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_health_regen);
        }
        self.dmg_save = self.dmg_save + save;//max(save - 10, 0);
        self.dmg_take = self.dmg_take + take;//max(take - 10, 0);
        self.dmg_inflictor = inflictor;
 
-       if (self.health <= -100 && self.modelindex != 0)
+       if (self.health <= -autocvar_sv_gibhealth && self.modelindex != 0)
        {
                // don't use any animations as a gib
                self.frame = 0;
@@ -382,16 +374,22 @@ void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float
                Violence_GibSplash(self, 1, 1, attacker);
                self.modelindex = 0; // restore later
                self.solid = SOLID_NOT; // restore later
+               self.takedamage = DAMAGE_NO; // restore later
        }
 }
 
 void ClientKill_Now_TeamChange();
+void freezetag_CheckWinner();
 
 void PlayerDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
 {
        local float take, save, waves, sdelay, dh, da, j;
        vector v;
        float valid_damage_for_weaponstats;
+       float excess;
+
+       if((g_arena && numspawned < 2) || (g_ca && ca_players < required_ca_players) && !inWarmupStage)
+               return;
 
        dh = max(self.health, 0);
        da = max(self.armorvalue, 0);
@@ -434,12 +432,9 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
        else
                Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
 
-       if((g_arena && numspawned < 2) || (g_ca && ca_players < required_ca_players) && !inWarmupStage)
-               return;
-
        if (!g_minstagib)
        {
-               v = healtharmor_applydamage(self.armorvalue, cvar("g_balance_armor_blockpercent"), damage);
+               v = healtharmor_applydamage(self.armorvalue, autocvar_g_balance_armor_blockpercent, damage);
                take = v_x;
                save = v_y;
        }
@@ -458,6 +453,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
        MUTATOR_CALLHOOK(PlayerDamage_SplitHealthArmor);
        take = bound(0, damage_take, self.health);
        save = bound(0, damage_save, self.armorvalue);
+       excess = max(0, damage - take - save);
 
        if(sound_allowed(MSG_BROADCAST, attacker))
        {
@@ -481,7 +477,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                        self.armorvalue = self.armorvalue - save;
                        self.health = self.health - take;
                        // pause regeneration for 5 seconds
-                       self.pauseregen_finished = max(self.pauseregen_finished, time + cvar("g_balance_pause_health_regen"));
+                       self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_health_regen);
 
                        if (time > self.pain_finished)          //Don't switch pain sequences like crazy
                        {
@@ -497,7 +493,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                                        }
 
                                        if(sound_allowed(MSG_BROADCAST, attacker))
-                                       if(!DEATH_ISWEAPON(deathtype, WEP_LASER) || attacker != self || self.health < 2 * cvar("g_balance_laser_primary_damage") * cvar("g_balance_selfdamagepercent") + 1)
+                                       if(!DEATH_ISWEAPON(deathtype, WEP_LASER) || attacker != self || self.health < 2 * autocvar_g_balance_laser_primary_damage * autocvar_g_balance_selfdamagepercent + 1)
                                        if(self.health > 1)
                                        // exclude pain sounds for laserjumps as long as you aren't REALLY low on health and would die of the next two
                                        {
@@ -537,7 +533,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
        else if(attacker.classname == "player" || attacker.classname == "gib")
        {
                self.pusher = attacker;
-               self.pushltime = time + cvar("g_maxpushtime");
+               self.pushltime = time + autocvar_g_maxpushtime;
        }
        else if(time < self.pushltime)
        {
@@ -547,19 +543,28 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
        else
                self.pushltime = 0;
 
+       float abot, vbot, awep;
+       abot = (clienttype(attacker) == CLIENTTYPE_BOT);
+       vbot = (clienttype(self) == CLIENTTYPE_BOT);
+
        valid_damage_for_weaponstats = 0;
-       if(clienttype(self) == CLIENTTYPE_REAL)
-       if(clienttype(attacker) == CLIENTTYPE_REAL)
-       if(self != attacker)
-       if(!DEATH_ISSPECIAL(deathtype))
+       if(vbot || clienttype(self) == CLIENTTYPE_REAL)
+       if(abot || clienttype(attacker) == CLIENTTYPE_REAL)
+       if(attacker && self != attacker)
        if(IsDifferentTeam(self, attacker))
+       {
+               if(DEATH_ISSPECIAL(deathtype))
+                       awep = attacker.weapon;
+               else
+                       awep = DEATH_WEAPONOF(deathtype);
                valid_damage_for_weaponstats = 1;
+       }
        
        if(valid_damage_for_weaponstats)
        {
                dh = dh - max(self.health, 0);
                da = da - max(self.armorvalue, 0);
-               WeaponStats_LogDamage(DEATH_WEAPONOF(deathtype), self.weapon, dh + da);
+               WeaponStats_LogDamage(awep, abot, self.weapon, vbot, dh + da);
        }
 
        if (self.health < 1)
@@ -574,7 +579,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                }
 
                if(valid_damage_for_weaponstats)
-                       WeaponStats_LogKill(DEATH_WEAPONOF(deathtype), self.weapon);
+                       WeaponStats_LogKill(awep, abot, self.weapon, vbot);
 
                if(sv_gentle < 1) // TODO make a "gentle" version?
                if(sound_allowed(MSG_BROADCAST, attacker))
@@ -601,17 +606,29 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                        }
                }
 
-               // become fully visible
-               self.alpha = 1;
-               // clear selected player display
-               ClearSelectedPlayer();
-               // throw a weapon
-               SpawnThrownWeapon (self.origin + (self.mins + self.maxs) * 0.5, self.switchweapon);
+               if(!g_freezetag)
+               {
+                       // become fully visible
+                       self.alpha = 1;
+                       // clear selected player display
+                       ClearSelectedPlayer();
+                       // throw a weapon
+                       SpawnThrownWeapon (self.origin + (self.mins + self.maxs) * 0.5, self.switchweapon);
+               }
+
                // print an obituary message
                Obituary (attacker, inflictor, self, deathtype);
                race_PreDie();
                DropAllRunes(self);
 
+               if(deathtype == DEATH_HURTTRIGGER && g_freezetag)
+               {
+                       PutClientInServer();
+                       count_alive_players(); // re-count players
+                       freezetag_CheckWinner();
+                       return;
+               }
+
                frag_attacker = attacker;
                frag_inflictor = inflictor;
                frag_target = self;
@@ -629,8 +646,31 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                if(self.ballcarried && g_nexball)
                        DropBall(self.ballcarried, self.origin, self.velocity);
                Portal_ClearAllLater(self);
-               // clear waypoints
+
+               if(clienttype(self) == CLIENTTYPE_REAL)
+               {
+                       stuffcmd(self, "-zoom\n");
+                       self.fixangle = TRUE;
+                       //msg_entity = self;
+                       //WriteByte (MSG_ONE, SVC_SETANGLE);
+                       //WriteAngle (MSG_ONE, self.v_angle_x);
+                       //WriteAngle (MSG_ONE, self.v_angle_y);
+                       //WriteAngle (MSG_ONE, 80);
+               }
+
+               if(defer_ClientKill_Now_TeamChange) // TODO does this work with FreezeTag?
+                       ClientKill_Now_TeamChange();
+
+               if(g_arena)
+                       Spawnqueue_Unmark(self);
+
+               if(g_freezetag)
+                       return;
+
+               // when we get here, player actually dies
+               // clear waypoints (do this AFTER FreezeTag)
                WaypointSprite_PlayerDead();
+
                // make the corpse upright (not tilted)
                self.angles_x = 0;
                self.angles_z = 0;
@@ -642,7 +682,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                self.movetype = MOVETYPE_TOSS;
                // shootable corpse
                self.solid = SOLID_CORPSE;
-               self.ballistics_density = cvar("g_ballistics_density_corpse");
+               self.ballistics_density = autocvar_g_ballistics_density_corpse;
                // don't stick to the floor
                self.flags &~= FL_ONGROUND;
                // dying animation
@@ -652,10 +692,15 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                waves = 0;
                sdelay = cvar(strcat("g_", GetGametype(), "_respawn_delay"));
                if(!sdelay)
-                       sdelay = cvar("g_respawn_delay");
+               {
+                       if(g_cts)
+                               sdelay = 0; // no respawn delay in CTS
+                       else
+                               sdelay = autocvar_g_respawn_delay;
+               }
                waves = cvar(strcat("g_", GetGametype(), "_respawn_waves"));
                if(!waves)
-                       waves = cvar("g_respawn_waves");
+                       waves = autocvar_g_respawn_waves;
                if(waves)
                        self.death_time = ceil((time + sdelay) / waves) * waves;
                else
@@ -677,35 +722,19 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                // set damage function to corpse damage
                self.event_damage = PlayerCorpseDamage;
                // call the corpse damage function just in case it wants to gib
-               self.event_damage(inflictor, attacker, 0, deathtype, hitloc, force);
+               self.event_damage(inflictor, attacker, excess, deathtype, hitloc, force);
                // set up to fade out later
                SUB_SetFade (self, time + 6 + random (), 1);
 
-               if(clienttype(self) == CLIENTTYPE_REAL)
-               {
-                       self.fixangle = TRUE;
-                       //msg_entity = self;
-                       //WriteByte (MSG_ONE, SVC_SETANGLE);
-                       //WriteAngle (MSG_ONE, self.v_angle_x);
-                       //WriteAngle (MSG_ONE, self.v_angle_y);
-                       //WriteAngle (MSG_ONE, 80);
-               }
-
-               if(g_arena)
-                       Spawnqueue_Unmark(self);
-
-               if(defer_ClientKill_Now_TeamChange)
-                       ClientKill_Now_TeamChange();
-
-               if(sv_gentle > 0 || cvar("ekg")) {
+               if(sv_gentle > 0 || autocvar_ekg) {
                        // remove corpse
-                       PlayerCorpseDamage (inflictor, attacker, 100.0, deathtype, hitloc, force);
+                       PlayerCorpseDamage (inflictor, attacker, autocvar_sv_gibhealth+1.0, deathtype, hitloc, force);
                }
 
                // reset fields the weapons may use just in case
-        for (j = WEP_FIRST; j <= WEP_LAST; ++j)
+               for (j = WEP_FIRST; j <= WEP_LAST; ++j)
                {
-            weapon_action(j, WR_RESETPLAYER);
+                       weapon_action(j, WR_RESETPLAYER);
                        ATTACK_FINISHED_FOR(self, j) = 0;
                }
        }
@@ -770,7 +799,7 @@ void UpdateSelectedPlayer()
        selected = world;
        selected_score = 0.95; // 18 degrees
 
-       if(!cvar("sv_allow_shownames"))
+       if(!autocvar_sv_allow_shownames)
                return;
 
        if(clienttype(self) != CLIENTTYPE_REAL)
@@ -906,7 +935,7 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
        }
        */
 
-       if(cvar("g_chat_teamcolors"))
+       if(autocvar_g_chat_teamcolors)
                namestr = playername(source);
        else
                namestr = source.netname;
@@ -919,7 +948,7 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
                        privatemsgprefixlen = strlen(msgstr);
                        msgstr = strcat(msgstr, msgin);
                        cmsgstr = strcat(colorstr, "^3", namestr, "^3 tells you:\n^7", msgin);
-                       if(cvar("g_chat_teamcolors"))
+                       if(autocvar_g_chat_teamcolors)
                                privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", playername(privatesay), ": ^7");
                        else
                                privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", privatesay.netname, ": ^7");
@@ -954,23 +983,23 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
                float lines;
                if(privatesay)
                {
-                       flood_spl = cvar("g_chat_flood_spl_tell");
-                       flood_burst = cvar("g_chat_flood_burst_tell");
-                       flood_lmax = cvar("g_chat_flood_lmax_tell");
+                       flood_spl = autocvar_g_chat_flood_spl_tell;
+                       flood_burst = autocvar_g_chat_flood_burst_tell;
+                       flood_lmax = autocvar_g_chat_flood_lmax_tell;
                        flood_field = floodcontrol_chattell;
                }
                else if(teamsay)
                {
-                       flood_spl = cvar("g_chat_flood_spl_team");
-                       flood_burst = cvar("g_chat_flood_burst_team");
-                       flood_lmax = cvar("g_chat_flood_lmax_team");
+                       flood_spl = autocvar_g_chat_flood_spl_team;
+                       flood_burst = autocvar_g_chat_flood_burst_team;
+                       flood_lmax = autocvar_g_chat_flood_lmax_team;
                        flood_field = floodcontrol_chatteam;
                }
                else
                {
-                       flood_spl = cvar("g_chat_flood_spl");
-                       flood_burst = cvar("g_chat_flood_burst");
-                       flood_lmax = cvar("g_chat_flood_lmax");
+                       flood_spl = autocvar_g_chat_flood_spl;
+                       flood_burst = autocvar_g_chat_flood_burst;
+                       flood_lmax = autocvar_g_chat_flood_lmax;
                        flood_field = floodcontrol_chat;
                }
                flood_burst = max(0, flood_burst - 1);
@@ -1019,7 +1048,7 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
 
        if(flood == 2) // cannot happen for empty msgstr
        {
-               if(cvar("g_chat_flood_notify_flooder"))
+               if(autocvar_g_chat_flood_notify_flooder)
                {
                        sourcemsgstr = strcat(msgstr, "\n^3FLOOD CONTROL: ^7message too long, trimmed\n");
                        sourcecmsgstr = "";
@@ -1040,7 +1069,7 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
        if(!privatesay)
        if(source.classname != "player")
        {
-               if(teamsay || (cvar("g_chat_nospectators") == 1) || (cvar("g_chat_nospectators") == 2 && !inWarmupStage))
+               if(teamsay || (autocvar_g_chat_nospectators == 1) || (autocvar_g_chat_nospectators == 2 && !inWarmupStage))
                        teamsay = -1; // spectators
        }
 
@@ -1058,7 +1087,7 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
        }
        else if(flood == 1)
        {
-               if(cvar("g_chat_flood_notify_flooder"))
+               if(autocvar_g_chat_flood_notify_flooder)
                {
                        sprint(source, strcat("^3FLOOD CONTROL: ^7wait ^1", ftos(source.flood_field - time), "^3 seconds\n"));
                        ret = 0;
@@ -1130,12 +1159,9 @@ float GetVoiceMessageVoiceType(string type)
 }
 
 string allvoicesamples;
-float GetPlayerSoundSampleField_notFound;
-float GetPlayerSoundSampleField_fixed;
 .string GetVoiceMessageSampleField(string type)
 {
        GetPlayerSoundSampleField_notFound = 0;
-       GetPlayerSoundSampleField_fixed = 0;
        switch(type)
        {
 #define _VOICEMSG(m) case #m: return playersound_##m;
@@ -1149,7 +1175,6 @@ float GetPlayerSoundSampleField_fixed;
 .string GetPlayerSoundSampleField(string type)
 {
        GetPlayerSoundSampleField_notFound = 0;
-       GetPlayerSoundSampleField_fixed = 0;
        switch(type)
        {
 #define _VOICEMSG(m) case #m: return playersound_##m;
@@ -1211,7 +1236,7 @@ void ClearPlayerSounds()
 #undef _VOICEMSG
 }
 
-void LoadPlayerSounds(string f, float first)
+float LoadPlayerSounds(string f, float first)
 {
        float fh;
        string s;
@@ -1220,7 +1245,7 @@ void LoadPlayerSounds(string f, float first)
        if(fh < 0)
        {
                dprint("Player sound file not found: ", f, "\n");
-               return;
+               return 0;
        }
        while((s = fgets(fh)))
        {
@@ -1231,14 +1256,12 @@ void LoadPlayerSounds(string f, float first)
                        field = GetVoiceMessageSampleField(argv(0));
                if(GetPlayerSoundSampleField_notFound)
                        continue;
-               if(GetPlayerSoundSampleField_fixed)
-                       if not(first)
-                               continue;
                if(self.field)
                        strunzone(self.field);
                self.field = strzone(strcat(argv(1), " ", argv(2)));
        }
        fclose(fh);
+       return 1;
 }
 
 .float modelindex_for_playersound;
@@ -1252,7 +1275,8 @@ void UpdatePlayerSounds()
        self.skinindex_for_playersound = self.skinindex;
        ClearPlayerSounds();
        LoadPlayerSounds("sound/player/default.sounds", 1);
-       LoadPlayerSounds(get_model_datafilename(self.playermodel, self.skinindex, "sounds"), 0);
+       if(!LoadPlayerSounds(get_model_datafilename(self.model, self.skinindex, "sounds"), 0))
+               LoadPlayerSounds(get_model_datafilename(self.model, 0, "sounds"), 0);
 }
 
 void FakeGlobalSound(string sample, float chan, float voicetype)