X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fcl_player.qc;h=16d413bd063a7552f904da7e565318f6a71d2029;hb=11528217faa0f195f0420dab30dd38f3d102934f;hp=202dce58c15b487902a2d17ef9ce06928d9d6566;hpb=c1f3f5b21dec034b543e314edc7dcc4f2da763c2;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/cl_player.qc b/qcsrc/server/cl_player.qc index 202dce58c..16d413bd0 100644 --- a/qcsrc/server/cl_player.qc +++ b/qcsrc/server/cl_player.qc @@ -1,3 +1,6 @@ +.entity accuracy; +.float accuracy_frags[WEP_MAXCOUNT]; + float weaponstats_buffer; void WeaponStats_Init() @@ -10,23 +13,26 @@ void WeaponStats_Init() #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() +void WeaponStats_ready(entity fh, entity pass, float status) { - float i, j, ibot, jbot, idx; - float fh; + float i, j, n, ibot, jbot, idx; vector v; - string prefix; - if(weaponstats_buffer < 0) - return; - prefix = strcat(autocvar_hostname, "\t", GetGametype(), "_", GetMapname(), "\t"); - if(autocvar_sv_weaponstats_file != "") + string prefix, s; + switch(status) { - fh = fopen(autocvar_sv_weaponstats_file, FILE_APPEND); - if(fh >= 0) - { - 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")); + case URL_READY_CANWRITE: + // url_fopen returned, we can write + prefix = strcat(autocvar_hostname, "\t", GetGametype(), "_", GetMapname(), "\t"); + url_fputs(fh, "#begin statsfile\n"); + url_fputs(fh, strcat("#date ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"), "\n")); +#ifdef WATERMARK + url_fputs(fh, strcat("#version ", WATERMARK(), "\n")); +#endif + url_fputs(fh, strcat("#config ", ftos(crc16(FALSE, cvar_purechanges)), "\n")); + url_fputs(fh, strcat("#cvar_purechanges ", ftos(cvar_purechanges_count), "\n")); + n = tokenizebyseparator(cvar_purechanges, "\n"); + for(i = 0; i < n; ++i) + url_fputs(fh, strcat("#cvar_purechange ", argv(i), "\n")); 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) { @@ -35,17 +41,48 @@ void WeaponStats_Shutdown() 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)); + url_fputs(fh, sprintf("%s%d %d\t%d %d\t", prefix, i, ibot, j, jbot)); + url_fputs(fh, sprintf("%d %d %g\n", v_x, v_y, v_z)); } } - fputs(fh, "#end\n\n"); - fclose(fh); + url_fputs(fh, "#end\n\n"); + url_fclose(fh, WeaponStats_ready, world); + buf_del(weaponstats_buffer); + weaponstats_buffer = -1; + break; + case URL_READY_CANREAD: + // url_fclose is processing, we got a response for writing the data + // this must come from HTTP + print("Got response from weapon stats server:\n"); + while((s = url_fgets(fh))) + print(" ", s, "\n"); + print("End of response.\n"); + url_fclose(fh, WeaponStats_ready, world); + break; + case URL_READY_CLOSED: + // url_fclose has finished print("Weapon stats written\n"); - } + break; + case URL_READY_ERROR: + default: + print("Weapon stats writing failed: ", ftos(status), "\n"); + break; + } +} + +void WeaponStats_Shutdown() +{ + if(weaponstats_buffer < 0) + return; + if(autocvar_sv_weaponstats_file != "") + { + url_fopen(autocvar_sv_weaponstats_file, FILE_APPEND, WeaponStats_ready, world); + } + else + { + buf_del(weaponstats_buffer); + weaponstats_buffer = -1; } - buf_del(weaponstats_buffer); - weaponstats_buffer = -1; } void WeaponStats_LogItem(float awep, float abot, float vwep, float vbot, vector item) @@ -337,11 +374,11 @@ void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float if(sound_allowed(MSG_BROADCAST, attacker)) { if (save > 10) - sound (self, CHAN_PROJECTILE, "misc/armorimpact.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS, "misc/armorimpact.wav", VOL_BASE, ATTN_NORM); else if (take > 30) - sound (self, CHAN_PROJECTILE, "misc/bodyimpact2.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS, "misc/bodyimpact2.wav", VOL_BASE, ATTN_NORM); else if (take > 10) - sound (self, CHAN_PROJECTILE, "misc/bodyimpact1.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS, "misc/bodyimpact1.wav", VOL_BASE, ATTN_NORM); } if (take > 50) @@ -454,11 +491,11 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht if(sound_allowed(MSG_BROADCAST, attacker)) { if (save > 10) - sound (self, CHAN_PROJECTILE, "misc/armorimpact.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS, "misc/armorimpact.wav", VOL_BASE, ATTN_NORM); else if (take > 30) - sound (self, CHAN_PROJECTILE, "misc/bodyimpact2.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS, "misc/bodyimpact2.wav", VOL_BASE, ATTN_NORM); else if (take > 10) - sound (self, CHAN_PROJECTILE, "misc/bodyimpact1.wav", VOL_BASE, ATTN_NORM); // FIXME possibly remove them? + sound (self, CH_SHOTS, "misc/bodyimpact1.wav", VOL_BASE, ATTN_NORM); // FIXME possibly remove them? } if (take > 50) @@ -494,15 +531,15 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht // 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) - PlayerSound(playersound_fall, CHAN_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_fall, CH_PAIN, VOICETYPE_PLAYERSOUND); else if(self.health > 75) // TODO make a "gentle" version? - PlayerSound(playersound_pain100, CHAN_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_pain100, CH_PAIN, VOICETYPE_PLAYERSOUND); else if(self.health > 50) - PlayerSound(playersound_pain75, CHAN_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_pain75, CH_PAIN, VOICETYPE_PLAYERSOUND); else if(self.health > 25) - PlayerSound(playersound_pain50, CHAN_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_pain50, CH_PAIN, VOICETYPE_PLAYERSOUND); else - PlayerSound(playersound_pain25, CHAN_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_pain25, CH_PAIN, VOICETYPE_PLAYERSOUND); } } @@ -526,7 +563,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht // escape a lava pit or similar //self.pushltime = 0; } - else if(attacker.classname == "player" || attacker.classname == "gib") + else if(attacker.classname == "player") { self.pusher = attacker; self.pushltime = time + autocvar_g_maxpushtime; @@ -555,7 +592,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht awep = DEATH_WEAPONOF(deathtype); valid_damage_for_weaponstats = 1; } - + if(valid_damage_for_weaponstats) { dh = dh - max(self.health, 0); @@ -581,9 +618,9 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht if(sound_allowed(MSG_BROADCAST, attacker)) { if(deathtype == DEATH_DROWN) - PlayerSound(playersound_drown, CHAN_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_drown, CH_PAIN, VOICETYPE_PLAYERSOUND); else - PlayerSound(playersound_death, CHAN_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_death, CH_PAIN, VOICETYPE_PLAYERSOUND); } // get rid of kill indicator @@ -606,8 +643,6 @@ 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); } @@ -617,6 +652,14 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht race_PreDie(); DropAllRunes(self); + // increment frag counter for used weapon type + float w; + w = DEATH_WEAPONOF(deathtype); + if(WEP_VALID(w)) + if(self.classname == "player") + if(self != attacker) + attacker.accuracy.(accuracy_frags[w-1]) += 1; + if(deathtype == DEATH_HURTTRIGGER && g_freezetag) { PutClientInServer(); @@ -633,7 +676,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht if(self.flagcarried) { - if(attacker.classname != "player" && attacker.classname != "gib") + if(attacker.classname != "player") DropFlag(self.flagcarried, self, attacker); // penalty for flag loss by suicide else if(attacker.team == self.team) DropFlag(self.flagcarried, attacker, attacker); // penalty for flag loss by suicide/teamkill @@ -737,154 +780,6 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht } } -float UpdateSelectedPlayer_countvalue(float v) -{ - return max(0, (v - 1.0) / 0.5); -} - -// returns: -2 if no hit, otherwise cos of the angle -// uses the global v_angle -float UpdateSelectedPlayer_canSee(entity p, float mincosangle, float maxdist) -{ - vector so, d; - float c; - - if(p == self) - return -2; - - if(p.deadflag) - return -2; - - so = self.origin + self.view_ofs; - d = p.origin - so; - - // misaimed? - if(dist_point_line(d, '0 0 0', v_forward) > maxdist) - return -2; - - // now find the cos of the angle... - c = normalize(d) * v_forward; - - if(c <= mincosangle) - return -2; - - // not visible in any way? forget it - if(!checkpvs(so, p)) - return -2; - - traceline(so, p.origin, MOVE_NOMONSTERS, self); - if(trace_fraction < 1) - return -2; - - return c; -} - -void ClearSelectedPlayer() -{ - if(self.selected_player) - { - centerprint_expire(self, CENTERPRIO_POINT); - self.selected_player = world; - self.selected_player_display_needs_update = FALSE; - } -} - -void UpdateSelectedPlayer() -{ - entity selected; - float selected_score; - selected = world; - selected_score = 0.95; // 18 degrees - - if(!autocvar_sv_allow_shownames) - return; - - if(clienttype(self) != CLIENTTYPE_REAL) - return; - - if(self.cvar_cl_shownames == 0) - return; - - if(self.cvar_cl_shownames == 1 && !teams_matter) - return; - - makevectors(self.v_angle); // sets v_forward - - // 1. cursor trace is always right - WarpZone_crosshair_trace(self); - if(trace_ent && trace_ent.classname == "player" && !trace_ent.deadflag) - { - selected = trace_ent; - } - else - { - // 2. if we don't have a cursor trace, find the player which is least - // mis-aimed at - entity p; - FOR_EACH_PLAYER(p) - { - float c; - c = UpdateSelectedPlayer_canSee(p, selected_score, 100); // 100 = 2.5 meters - if(c >= -1) - { - selected = p; - selected_score = c; - } - } - } - - if(selected) - { - self.selected_player_display_timeout = time + self.cvar_scr_centertime; - } - else - { - if(time < self.selected_player_display_timeout) - if(UpdateSelectedPlayer_canSee(self.selected_player, 0.7, 200) >= -1) // 5 meters, 45 degrees - selected = self.selected_player; - } - - if(selected) - { - if(selected == self.selected_player) - { - float save; - save = UpdateSelectedPlayer_countvalue(self.selected_player_count); - self.selected_player_count = self.selected_player_count + frametime; - if(save != UpdateSelectedPlayer_countvalue(self.selected_player_count)) - { - string namestr, healthstr; - namestr = playername(selected); - if(teams_matter) - { - healthstr = ftos(floor(selected.health)); - if(self.team == selected.team) - { - namestr = strcat(namestr, " (", healthstr, "%)"); - self.selected_player_display_needs_update = TRUE; - } - } - centerprint_atprio(self, CENTERPRIO_POINT, namestr); - } - } - else - { - ClearSelectedPlayer(); - self.selected_player = selected; - self.selected_player_time = time; - self.selected_player_count = 0; - self.selected_player_display_needs_update = FALSE; - } - } - else - { - ClearSelectedPlayer(); - } - - if(self.selected_player) - self.last_selected_player = self.selected_player; -} - .float muted; // to be used by prvm_edictset server playernumber muted 1 float Say(entity source, float teamsay, entity privatesay, string msgin, float floodcontrol) // message "": do not say, just test flood control @@ -910,7 +805,7 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f if(source.classname != "player") colorstr = "^0"; // black for spectators - else if(teams_matter) + else if(teamplay) colorstr = Team_ColorCode(source.team); else teamsay = FALSE; @@ -1272,8 +1167,9 @@ void UpdatePlayerSounds() self.skinindex_for_playersound = self.skinindex; ClearPlayerSounds(); LoadPlayerSounds("sound/player/default.sounds", 1); - if(!LoadPlayerSounds(get_model_datafilename(self.model, self.skinindex, "sounds"), 0)) - LoadPlayerSounds(get_model_datafilename(self.model, 0, "sounds"), 0); + if(!autocvar_g_debug_defaultsounds) + 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) @@ -1399,7 +1295,7 @@ void GlobalSound(string sample, float chan, float voicetype) break; case VOICETYPE_TEAMRADIO: FOR_EACH_REALCLIENT(msg_entity) - if(!teams_matter || msg_entity.team == self.team) + if(!teamplay || msg_entity.team == self.team) { if(msg_entity.cvar_cl_voice_directional == 1) soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_MIN); @@ -1473,9 +1369,9 @@ void VoiceMessage(string type, string msg) flood = Say(self, ownteam, world, msg, 1); if (flood > 0) - GlobalSound(self.sample, CHAN_VOICE, voicetype); + GlobalSound(self.sample, CH_VOICE, voicetype); else if (flood < 0) - FakeGlobalSound(self.sample, CHAN_VOICE, voicetype); + FakeGlobalSound(self.sample, CH_VOICE, voicetype); } void MoveToTeam(entity client, float team_colour, float type, float show_message)