X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fcl_player.qc;h=e194b026f9dd1b802e115a6b67f389c9d1c97798;hb=d95afcf1229a11a7198936683998d16a1c2500d7;hp=b49488b0553701cb528de71fd1261c0326c38e65;hpb=317ec3eb27ada1c4668876e9499136125acb7984;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/cl_player.qc b/qcsrc/server/cl_player.qc index b49488b05..e194b026f 100644 --- a/qcsrc/server/cl_player.qc +++ b/qcsrc/server/cl_player.qc @@ -9,6 +9,7 @@ #include "teamplay.qh" #include "weapons/throwing.qh" #include "command/common.qh" +#include "../common/anim.qh" #include "../common/animdecide.qh" #include "../common/csqcmodel_settings.qh" #include "../common/deathtypes/all.qh" @@ -153,17 +154,7 @@ void player_anim () if(self.crouch) animbits |= ANIMSTATE_DUCK; animdecide_setstate(self, animbits, false); - animdecide_setimplicitstate(self, (self.flags & FL_ONGROUND)); - - .entity weaponentity = weaponentities[0]; // TODO: unhardcode - { - if (self.(weaponentity)) - { - updateanim(self.(weaponentity)); - if (!self.(weaponentity).animstate_override) - setanim(self.(weaponentity), self.(weaponentity).anim_idle, true, false, false); - } - } + animdecide_setimplicitstate(self, (IS_ONGROUND(self))); } void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force) @@ -218,8 +209,8 @@ void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, int de } } -void calculate_player_respawn_time() -{SELFPARAM(); +void calculate_player_respawn_time(entity this) +{ if(g_ca) return; @@ -232,13 +223,12 @@ void calculate_player_respawn_time() float waves = GAMETYPE_DEFAULTED_SETTING(respawn_waves); float pcount = 1; // Include myself whether or not team is already set right and I'm a "player". - entity pl; if (teamplay) { - FOR_EACH_PLAYER(pl) - if (pl != self) - if (pl.team == self.team) - ++pcount; + FOREACH_CLIENT(IS_PLAYER(it) && it != this, LAMBDA( + if(it.team == this.team) + ++pcount; + )); if (sdelay_small_count == 0) sdelay_small_count = 1; if (sdelay_large_count == 0) @@ -246,9 +236,9 @@ void calculate_player_respawn_time() } else { - FOR_EACH_PLAYER(pl) - if (pl != self) - ++pcount; + FOREACH_CLIENT(IS_PLAYER(it) && it != this, LAMBDA( + ++pcount; + )); if (sdelay_small_count == 0) { if (g_cts) @@ -287,28 +277,27 @@ void calculate_player_respawn_time() sdelay = sdelay_small + (sdelay_large - sdelay_small) * (pcount - sdelay_small_count) / (sdelay_large_count - sdelay_small_count); if(waves) - self.respawn_time = ceil((time + sdelay) / waves) * waves; + this.respawn_time = ceil((time + sdelay) / waves) * waves; else - self.respawn_time = time + sdelay; + this.respawn_time = time + sdelay; if(sdelay < sdelay_max) - self.respawn_time_max = time + sdelay_max; + this.respawn_time_max = time + sdelay_max; else - self.respawn_time_max = self.respawn_time; + this.respawn_time_max = this.respawn_time; - if((sdelay + waves >= 5.0) && (self.respawn_time - time > 1.75)) - self.respawn_countdown = 10; // first number to count down from is 10 + if((sdelay + waves >= 5.0) && (this.respawn_time - time > 1.75)) + this.respawn_countdown = 10; // first number to count down from is 10 else - self.respawn_countdown = -1; // do not count down + this.respawn_countdown = -1; // do not count down if(autocvar_g_forced_respawn) - self.respawn_flags = self.respawn_flags | RESPAWN_FORCE; + this.respawn_flags = this.respawn_flags | RESPAWN_FORCE; } void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force) {SELFPARAM(); float take, save, dh, da; - int j; vector v; float valid_damage_for_weaponstats; float excess; @@ -439,15 +428,15 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp // exclude pain sounds for laserjumps as long as you aren't REALLY low on health and would die of the next two { if(deathtype == DEATH_FALL.m_id) - PlayerSound(playersound_fall, CH_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(self, playersound_fall, CH_PAIN, VOICETYPE_PLAYERSOUND); else if(self.health > 75) // TODO make a "gentle" version? - PlayerSound(playersound_pain100, CH_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(self, playersound_pain100, CH_PAIN, VOICETYPE_PLAYERSOUND); else if(self.health > 50) - PlayerSound(playersound_pain75, CH_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(self, playersound_pain75, CH_PAIN, VOICETYPE_PLAYERSOUND); else if(self.health > 25) - PlayerSound(playersound_pain50, CH_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(self, playersound_pain50, CH_PAIN, VOICETYPE_PLAYERSOUND); else - PlayerSound(playersound_pain25, CH_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(self, playersound_pain25, CH_PAIN, VOICETYPE_PLAYERSOUND); } } } @@ -491,7 +480,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp if(DIFF_TEAM(self, attacker)) { if(DEATH_ISSPECIAL(deathtype)) - awep = get_weaponinfo(attacker.weapon); + awep = PS(attacker).m_weapon; else awep = DEATH_WEAPONOF(deathtype); valid_damage_for_weaponstats = 1; @@ -501,7 +490,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp { dh = dh - max(self.health, 0); da = da - max(self.armorvalue, 0); - WeaponStats_LogDamage(awep.m_id, abot, self.weapon, vbot, dh + da); + WeaponStats_LogDamage(awep.m_id, abot, PS(self).m_weapon.m_id, vbot, dh + da); MUTATOR_CALLHOOK(PlayerDamaged, attacker, self, dh, da, hitloc, deathtype); } @@ -517,15 +506,15 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp } if(valid_damage_for_weaponstats) - WeaponStats_LogKill(awep.m_id, abot, self.weapon, vbot); + WeaponStats_LogKill(awep.m_id, abot, PS(self).m_weapon.m_id, vbot); if(autocvar_sv_gentle < 1) // TODO make a "gentle" version? if(sound_allowed(MSG_BROADCAST, attacker)) { if(deathtype == DEATH_DROWN.m_id) - PlayerSound(playersound_drown, CH_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(self, playersound_drown, CH_PAIN, VOICETYPE_PLAYERSOUND); else - PlayerSound(playersound_death, CH_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(self, playersound_death, CH_PAIN, VOICETYPE_PLAYERSOUND); } // get rid of kill indicator @@ -557,7 +546,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp MUTATOR_CALLHOOK(PlayerDies, inflictor, attacker, self, deathtype); excess = frag_damage; - Weapon wep = get_weaponinfo(self.weapon); + Weapon wep = PS(self).m_weapon; wep.wr_playerdeath(wep); RemoveGrapplingHook(self); @@ -582,7 +571,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp // clear waypoints WaypointSprite_PlayerDead(); // throw a weapon - SpawnThrownWeapon (self.origin + (self.mins + self.maxs) * 0.5, self.switchweapon); + SpawnThrownWeapon (self.origin + (self.mins + self.maxs) * 0.5, PS(self).m_switchweapon.m_id); // become fully visible self.alpha = default_player_alpha; @@ -599,12 +588,12 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp self.solid = SOLID_CORPSE; self.ballistics_density = autocvar_g_ballistics_density_corpse; // don't stick to the floor - self.flags &= ~FL_ONGROUND; + UNSET_ONGROUND(self); // dying animation self.deadflag = DEAD_DYING; // when to allow respawn - calculate_player_respawn_time(); + calculate_player_respawn_time(this); self.death_time = time; if (random() < 0.5) @@ -638,15 +627,13 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp } // reset fields the weapons may use just in case - for (j = WEP_FIRST; j <= WEP_LAST; ++j) - { - Weapon w = get_weaponinfo(j); - w.wr_resetplayer(w); - for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + FOREACH(Weapons, it != WEP_Null, LAMBDA( + it.wr_resetplayer(it); + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) { - ATTACK_FINISHED_FOR(self, j, slot) = 0; + ATTACK_FINISHED_FOR(self, it.m_id, slot) = 0; } - } + )); } } @@ -673,7 +660,6 @@ int Say(entity source, float teamsay, entity privatesay, string msgin, bool floo string msgstr, colorstr, cmsgstr, namestr, fullmsgstr, sourcemsgstr, fullcmsgstr, sourcecmsgstr, colorprefix; float flood; var .float flood_field; - entity head; float ret; string privatemsgprefix = string_null; float privatemsgprefixlen = 0; @@ -918,10 +904,7 @@ int Say(entity source, float teamsay, entity privatesay, string msgin, bool floo { sprint(source, sourcemsgstr); dedicated_print(msgstr); // send to server console too - FOR_EACH_REALCLIENT(head) - if(head != source) - if(head.active_minigame == source.active_minigame) - sprint(head, msgstr); + FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && it.active_minigame == source.active_minigame, LAMBDA(sprint(it, msgstr))); } else if(teamsay > 0) // team message, only sent to team mates { @@ -929,29 +912,23 @@ int Say(entity source, float teamsay, entity privatesay, string msgin, bool floo dedicated_print(msgstr); // send to server console too if(sourcecmsgstr != "") centerprint(source, sourcecmsgstr); - FOR_EACH_REALPLAYER(head) if(head.team == source.team) - if(head != source) - { - sprint(head, msgstr); - if(cmsgstr != "") - centerprint(head, cmsgstr); - } + FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && it != source && it.team == source.team, LAMBDA( + sprint(it, msgstr); + if(cmsgstr != "") + centerprint(it, cmsgstr); + )); } else if(teamsay < 0) // spectator message, only sent to spectators { sprint(source, sourcemsgstr); dedicated_print(msgstr); // send to server console too - FOR_EACH_REALCLIENT(head) if (!IS_PLAYER(head)) - if(head != source) - sprint(head, msgstr); + FOREACH_CLIENT(!IS_PLAYER(it) && IS_REAL_CLIENT(it) && it != source, LAMBDA(sprint(it, msgstr))); } else if(sourcemsgstr != msgstr) // trimmed/server fixed message, sent to all players { sprint(source, sourcemsgstr); dedicated_print(msgstr); // send to server console too - FOR_EACH_REALCLIENT(head) - if(head != source) - sprint(head, msgstr); + FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source, LAMBDA(sprint(it, msgstr))); } else bprint(msgstr); // entirely normal message, sent to all players -- bprint sends to server console too. @@ -959,282 +936,3 @@ int Say(entity source, float teamsay, entity privatesay, string msgin, bool floo return ret; } - -int GetVoiceMessageVoiceType(string type) -{ - if (type == "taunt") return VOICETYPE_TAUNT; - if (type == "teamshoot") return VOICETYPE_LASTATTACKER; - return VOICETYPE_TEAMRADIO; -} - -.string GetVoiceMessageSampleField(string type) -{ - GetPlayerSoundSampleField_notFound = false; - switch (type) - { -#define X(m) case #m: return playersound_##m; - ALLVOICEMSGS(X) -#undef X - } - GetPlayerSoundSampleField_notFound = true; - return playersound_taunt; -} - -.string GetPlayerSoundSampleField(string type) -{ - GetPlayerSoundSampleField_notFound = false; - switch (type) - { -#define X(m) case #m: return playersound_##m; - ALLPLAYERSOUNDS(X) -#undef X - } - GetPlayerSoundSampleField_notFound = true; - return playersound_taunt; -} - -void PrecacheGlobalSound(string sample) -{ - int n; - { - string s = cdr(sample); - if (s) n = stof(s); - else n = 0; - } - sample = car(sample); - if (n > 0) - { - for (int i = 1; i <= n; ++i) - precache_sound(sprintf("%s%d.wav", sample, i)); - } - else - { - precache_sound(sprintf("%s.wav", sample)); - } -} - -string allvoicesamples; - -void PrecachePlayerSounds(string f) -{ - int fh = fopen(f, FILE_READ); - if (fh < 0) - { - LOG_WARNINGF("Player sound file not found: %s\n", f); - return; - } - for (string s; (s = fgets(fh)); ) - { - int n = tokenize_console(s); - if (n != 3) - { - if (n != 0) LOG_WARNINGF("Invalid sound info line: %s\n", s); - continue; - } - string file = argv(1); - string variants = argv(2); - PrecacheGlobalSound(strcat(file, " ", variants)); - } - fclose(fh); - - if (!allvoicesamples) - { -#define X(m) allvoicesamples = strcat(allvoicesamples, " ", #m); - ALLVOICEMSGS(X) -#undef X - allvoicesamples = strzone(substring(allvoicesamples, 1, -1)); - } -} - -void ClearPlayerSounds(entity this) -{ -#define X(m) if (this.playersound_##m) { strunzone(this.playersound_##m); this.playersound_##m = string_null; } - ALLPLAYERSOUNDS(X) - ALLVOICEMSGS(X) -#undef X -} - -bool LoadPlayerSounds(string f, bool strict) -{ - SELFPARAM(); - int fh = fopen(f, FILE_READ); - if (fh < 0) - { - if (strict) LOG_WARNINGF("Player sound file not found: %s\n", f); - return false; - } - for (string s; (s = fgets(fh)); ) - { - int n = tokenize_console(s); - if (n != 3) - { - if (n != 0) LOG_WARNINGF("Invalid sound info line: %s\n", s); - continue; - } - string key = argv(0); - var .string field = GetPlayerSoundSampleField(key); - if (GetPlayerSoundSampleField_notFound) field = GetVoiceMessageSampleField(key); - if (GetPlayerSoundSampleField_notFound) - { - LOG_TRACEF("Invalid sound info field: %s\n", key); - continue; - } - string file = argv(1); - string variants = argv(2); - if (self.(field)) strunzone(self.(field)); - self.(field) = strzone(strcat(file, " ", variants)); - } - fclose(fh); - return true; -} - -.int modelindex_for_playersound; -.int skin_for_playersound; - -void UpdatePlayerSounds(entity this) -{ - if (this.modelindex == this.modelindex_for_playersound && this.skin == this.skin_for_playersound) return; - this.modelindex_for_playersound = this.modelindex; - this.skin_for_playersound = this.skin; - ClearPlayerSounds(this); - LoadPlayerSounds("sound/player/default.sounds", true); - if (autocvar_g_debug_defaultsounds) return; - if (!LoadPlayerSounds(get_model_datafilename(this.model, this.skin, "sounds"), false)) - LoadPlayerSounds(get_model_datafilename(this.model, 0, "sounds"), true); -} - -void _GlobalSound(string sample, int chan, int voicetype, bool fake) -{ - SELFPARAM(); - if (sample == "") return; - int n; - { - string s = cdr(sample); - if (s) n = stof(s); - else n = 0; - } - sample = car(sample); - if (n > 0) sample = sprintf("%s%d.wav", sample, floor(random() * n + 1)); // randomization - else sample = sprintf("%s.wav", sample); - switch (voicetype) - { - case VOICETYPE_LASTATTACKER_ONLY: - case VOICETYPE_LASTATTACKER: - { - if (!fake) - { - if (!this.pusher) break; - msg_entity = this.pusher; - if (IS_REAL_CLIENT(msg_entity)) - { - float atten = (msg_entity.cvar_cl_voice_directional == 1) ? ATTEN_MIN : ATTEN_NONE; - soundto(MSG_ONE, this, chan, sample, VOL_BASEVOICE, atten); - } - } - if (voicetype == VOICETYPE_LASTATTACKER_ONLY) break; - msg_entity = this; - if (IS_REAL_CLIENT(msg_entity)) soundto(MSG_ONE, this, chan, sample, VOL_BASE, ATTEN_NONE); - break; - } - case VOICETYPE_TEAMRADIO: - { - #define X() \ - do \ - { \ - float atten = (msg_entity.cvar_cl_voice_directional == 1) ? ATTEN_MIN : ATTEN_NONE; \ - soundto(MSG_ONE, this, chan, sample, VOL_BASEVOICE, atten); \ - } \ - while (0) - - if (fake) { msg_entity = this; X(); } - else - { - FOR_EACH_REALCLIENT(msg_entity) - { - if (!teamplay || msg_entity.team == this.team) X(); - } - } - #undef X - break; - } - case VOICETYPE_AUTOTAUNT: - case VOICETYPE_TAUNT: - { - if (voicetype == VOICETYPE_AUTOTAUNT) if (!sv_autotaunt) { break; }else {} - else if (IS_PLAYER(this) && this.deadflag == DEAD_NO) animdecide_setaction(this, ANIMACTION_TAUNT, true); - if (!sv_taunt) break; - if (autocvar_sv_gentle) break; - float tauntrand = 0; - if (voicetype == VOICETYPE_AUTOTAUNT) tauntrand = random(); - #define X() \ - do \ - { \ - if (voicetype != VOICETYPE_AUTOTAUNT || tauntrand < msg_entity.cvar_cl_autotaunt) \ - { \ - float atten = (msg_entity.cvar_cl_voice_directional >= 1) \ - ? bound(ATTEN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTEN_MAX) \ - : ATTEN_NONE; \ - soundto(MSG_ONE, this, chan, sample, VOL_BASEVOICE, atten); \ - } \ - } \ - while (0) - if (fake) - { - msg_entity = this; - X(); - } - else - { - FOR_EACH_REALCLIENT(msg_entity) - { - X(); - } - } - #undef X - break; - } - case VOICETYPE_PLAYERSOUND: - { - if (fake) - { - msg_entity = this; - soundto(MSG_ONE, this, chan, sample, VOL_BASE, ATTEN_NORM); - } - else - { - _sound(this, chan, sample, VOL_BASE, ATTEN_NORM); - } - break; - } - default: - { - backtrace("Invalid voice type!"); - break; - } - } -} - -void PlayerSound(.string samplefield, int chan, float voicetype) -{ - SELFPARAM(); - _GlobalSound(this.(samplefield), chan, voicetype, false); -} - -void VoiceMessage(string type, string msg) -{ - SELFPARAM(); - var .string sample = GetVoiceMessageSampleField(type); - if (GetPlayerSoundSampleField_notFound) - { - sprint(this, sprintf("Invalid voice. Use one of: %s\n", allvoicesamples)); - return; - } - int voicetype = GetVoiceMessageVoiceType(type); - bool ownteam = (voicetype == VOICETYPE_TEAMRADIO); - int flood = Say(this, ownteam, world, msg, true); - bool fake; - if (IS_SPEC(this) || IS_OBSERVER(this) || flood < 0) fake = true; - else if (flood > 0) fake = false; - else return; - _GlobalSound(this.(sample), CH_VOICE, voicetype, fake); -}