X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fclient%2Fmain.qc;h=04cafebbd3a341786d40a29acc313c9b321620c0;hp=c621e9fab3c9bf3f9024e2f0603aa7ac7dce5d26;hb=991de5e6922cd3c283de56c3249624f0f1bfe767;hpb=050fb0011ae5fb2b36c7c7f3d560f9453807a8ab diff --git a/qcsrc/client/main.qc b/qcsrc/client/main.qc index c621e9fab..04cafebbd 100644 --- a/qcsrc/client/main.qc +++ b/qcsrc/client/main.qc @@ -1,14 +1,21 @@ #include "main.qh" -#include +#include "defs.qh" +#include +#include "miscfunctions.qh" +#include +#include +#include +#include #include "hud/_mod.qh" +#include "commands/cl_cmd.qh" #include "mapvoting.qh" -#include "mutators/events.qh" +#include #include "hud/panel/scoreboard.qh" #include "hud/panel/quickmenu.qh" #include "shownames.qh" +#include "view.qh" #include -#include "wall.qh" #include "weapons/projectile.qh" #include #include @@ -18,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -85,13 +92,12 @@ void LoadMenuSkinValues() // CSQC_Init : Called every time the CSQC code is initialized (essentially at map load) // Useful for precaching things -void ConsoleCommand_macro_init(); void CSQC_Init() { prvm_language = strzone(cvar_string("prvm_language")); #ifdef WATERMARK - LOG_INFOF("^4CSQC Build information: ^1%s\n", WATERMARK); + LOG_INFOF("^4CSQC Build information: ^1%s", WATERMARK); #endif { @@ -128,10 +134,15 @@ void CSQC_Init() registercvar("cl_jumpspeedcap_min", ""); registercvar("cl_jumpspeedcap_max", ""); + registercvar("cl_shootfromfixedorigin", ""); + registercvar("cl_multijump", "1"); registercvar("cl_spawn_near_teammate", "1"); + registercvar("cl_weapon_switch_reload", "1"); + registercvar("cl_weapon_switch_fallback_to_impulse", "1"); + if(autocvar_cl_lockview) cvar_set("cl_lockview", "0"); @@ -146,6 +157,9 @@ void CSQC_Init() GetTeam(NUM_SPECTATOR, true); // add specs first + for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) + weapon_accuracy[w] = -1; + // precaches if(autocvar_cl_reticle) @@ -212,14 +226,16 @@ void Shutdown() localcmd("\ncl_hook_shutdown\n"); + localcmd("\n-button12\n"); + deactivate_minigame(); HUD_MinigameMenu_Close(NULL, NULL, NULL); } .float has_team; -float SetTeam(entity o, int Team) +bool SetTeam(entity o, int Team) { - TC(int, Team); + TC(int, Team); devassert_once(Team); entity tm; if(teamplay) @@ -292,7 +308,7 @@ float SetTeam(entity o, int Team) void Playerchecker_Think(entity this) { - int i; + int i; entity e; for(i = 0; i < maxclients; ++i) { @@ -332,7 +348,6 @@ void Playerchecker_Think(entity this) this.nextthink = time + 0.2; } -void TrueAim_Init(); void PostInit() { entity playerchecker = new_pure(playerchecker); @@ -353,20 +368,21 @@ void PostInit() // In the case of mouse input after a setcursormode(1) call, nPrimary is xpos, nSecondary is ypos. float CSQC_InputEvent(int bInputType, float nPrimary, float nSecondary) { - TC(int, bInputType); - if (HUD_Panel_InputEvent(bInputType, nPrimary, nSecondary)) + TC(int, bInputType); + bool override = false; + override |= HUD_Panel_InputEvent(bInputType, nPrimary, nSecondary); + if (override) return true; - if (QuickMenu_InputEvent(bInputType, nPrimary, nSecondary)) - return true; + override |= QuickMenu_InputEvent(bInputType, nPrimary, nSecondary); - if (HUD_Radar_InputEvent(bInputType, nPrimary, nSecondary)) - return true; + override |= HUD_Radar_InputEvent(bInputType, nPrimary, nSecondary); - if (MapVote_InputEvent(bInputType, nPrimary, nSecondary)) - return true; + override |= MapVote_InputEvent(bInputType, nPrimary, nSecondary); - if (HUD_Minigame_InputEvent(bInputType, nPrimary, nSecondary)) + override |= HUD_Minigame_InputEvent(bInputType, nPrimary, nSecondary); + + if(override) return true; return false; @@ -378,8 +394,6 @@ float CSQC_InputEvent(int bInputType, float nPrimary, float nSecondary) // -------------------------------------------------------------------------- // BEGIN OPTIONAL CSQC FUNCTIONS -void Ent_Remove(entity this); - void Ent_RemovePlayerScore(entity this) { if(this.owner) { @@ -405,7 +419,7 @@ NET_HANDLE(ENT_CLIENT_SCORES, bool isnew) if(!isNew && n != this.sv_entnum) { //print("A CSQC entity changed its owner!\n"); - LOG_INFOF("A CSQC entity changed its owner! (edict: %d, classname: %s)\n", etof(this), this.classname); + LOG_INFOF("A CSQC entity changed its owner! (edict: %d, classname: %s)", etof(this), this.classname); isNew = true; Ent_Remove(this); } @@ -426,11 +440,10 @@ NET_HANDLE(ENT_CLIENT_SCORES, bool isnew) // RegisterPlayer(o); //playerchecker will do this for us later, if it has not already done so - int sf, lf; - sf = ReadShort(); - lf = ReadShort(); + int sf = ReadShort(); + int lf = ReadShort(); FOREACH(Scores, true, { - int p = 1 << (i % 16); + int p = 1 << (i % 16); if (sf & p) { if (lf & p) @@ -438,7 +451,7 @@ NET_HANDLE(ENT_CLIENT_SCORES, bool isnew) else o.(scores(it)) = ReadChar(); } - }); + }); return = true; @@ -452,24 +465,21 @@ NET_HANDLE(ENT_CLIENT_TEAMSCORES, bool isnew) { make_pure(this); int i; - entity o; this.team = ReadByte(); - o = this.owner = GetTeam(this.team, true); // these team numbers can always be trusted + entity o = this.owner = GetTeam(this.team, true); // these team numbers can always be trusted - int sf, lf; #if MAX_TEAMSCORE <= 8 - sf = ReadByte(); - lf = ReadByte(); + int sf = ReadByte(); + int lf = ReadByte(); #else - sf = ReadShort(); - lf = ReadShort(); + int sf = ReadShort(); + int lf = ReadShort(); #endif - int p; - for(i = 0, p = 1; i < MAX_TEAMSCORE; ++i, p *= 2) - if(sf & p) + for(i = 0; i < MAX_TEAMSCORE; ++i) + if(sf & BIT(i)) { - if(lf & p) + if(lf & BIT(i)) o.(teamscores(i)) = ReadInt24_t(); else o.(teamscores(i)) = ReadChar(); @@ -485,11 +495,11 @@ NET_HANDLE(ENT_CLIENT_CLIENTDATA, bool isnew) make_pure(this); float newspectatee_status; - int f = ReadByte(); + int f = ReadByte(); - scoreboard_showscores_force = (f & 1); + scoreboard_showscores_force = (f & BIT(0)); - if(f & 2) + if(f & BIT(1)) { newspectatee_status = ReadByte(); if(newspectatee_status == player_localnum + 1) @@ -498,9 +508,9 @@ NET_HANDLE(ENT_CLIENT_CLIENTDATA, bool isnew) else newspectatee_status = 0; - spectatorbutton_zoom = (f & 4); + spectatorbutton_zoom = (f & BIT(2)); - if(f & 16) + if(f & BIT(4)) { num_spectators = ReadByte(); @@ -524,6 +534,7 @@ NET_HANDLE(ENT_CLIENT_CLIENTDATA, bool isnew) race_laptime = 0; race_checkpointtime = 0; hud_dynamic_shake_factor = -1; + spectatee_status_changed_time = time; } if (autocvar_hud_panel_healtharmor_progressbar_gfx) { @@ -542,15 +553,13 @@ NET_HANDLE(ENT_CLIENT_CLIENTDATA, bool isnew) NET_HANDLE(ENT_CLIENT_NAGGER, bool isnew) { make_pure(this); - int i, j, b, f; + int i, j, b, f; - int nags = ReadByte(); // NAGS NAGS NAGS NAGS NAGS NAGS NADZ NAGS NAGS NAGS + int nags = ReadByte(); // NAGS NAGS NAGS NAGS NAGS NAGS NADZ NAGS NAGS NAGS if(!(nags & BIT(2))) { - if(vote_called_vote) - strunzone(vote_called_vote); - vote_called_vote = string_null; + strfree(vote_called_vote); vote_active = 0; } else @@ -568,23 +577,21 @@ NET_HANDLE(ENT_CLIENT_NAGGER, bool isnew) if(nags & BIT(7)) { - if(vote_called_vote) - strunzone(vote_called_vote); - vote_called_vote = strzone(ReadString()); + strcpy(vote_called_vote, ReadString()); } if(nags & 1) { for(j = 0; j < maxclients; ++j) if(playerslots[j]) - playerslots[j].ready = 1; + playerslots[j].ready = true; for(i = 1; i <= maxclients; i += 8) { f = ReadByte(); - for(j = i-1, b = 1; b < 256; b *= 2, ++j) + for(j = i-1, b = BIT(0); b < BIT(8); b <<= 1, ++j) if (!(f & b)) if(playerslots[j]) - playerslots[j].ready = 0; + playerslots[j].ready = false; } } @@ -600,21 +607,24 @@ NET_HANDLE(ENT_CLIENT_NAGGER, bool isnew) NET_HANDLE(ENT_CLIENT_ELIMINATEDPLAYERS, bool isnew) { make_pure(this); - int i, j, b, f; - - int sf = ReadByte(); - if(sf & 1) - { - for(j = 0; j < maxclients; ++j) - if(playerslots[j]) - playerslots[j].eliminated = 1; - for(i = 1; i <= maxclients; i += 8) - { - f = ReadByte(); - for(j = i-1, b = 1; b < 256; b *= 2, ++j) - if (!(f & b)) - if(playerslots[j]) - playerslots[j].eliminated = 0; + int sf = 0; + serialize(byte, 0, sf); + if (sf & 1) { + for (int j = 0; j < maxclients; ++j) { + if (playerslots[j]) { + playerslots[j].eliminated = true; + } + } + for (int i = 1; i <= maxclients; i += 8) { + int f = 0; + serialize(byte, 0, f); + for (int b = 0; b < 8; ++b) { + if (f & BIT(b)) continue; + int j = i - 1 + b; + if (playerslots[j]) { + playerslots[j].eliminated = false; + } + } } } return true; @@ -632,7 +642,7 @@ NET_HANDLE(ENT_CLIENT_RANDOMSEED, bool isnew) NET_HANDLE(ENT_CLIENT_ACCURACY, bool isnew) { make_pure(this); - int sf = ReadInt24_t(); + int sf = ReadInt24_t(); if (sf == 0) { for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) weapon_accuracy[w] = -1; @@ -642,7 +652,7 @@ NET_HANDLE(ENT_CLIENT_ACCURACY, bool isnew) int f = 1; for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) { if (sf & f) { - int b = ReadByte(); + int b = ReadByte(); if (b == 0) weapon_accuracy[w] = -1; else if (b == 255) @@ -657,6 +667,9 @@ NET_HANDLE(ENT_CLIENT_ACCURACY, bool isnew) void Spawn_Draw(entity this) { + if(this.alpha <= 0) + return; + __pointparticles(this.cnt, this.origin + '0 0 28', '0 0 2', bound(0, frametime, 0.1)); } @@ -665,7 +678,14 @@ void Spawn_PreDraw(entity this) float alph; vector org = getpropertyvec(VF_ORIGIN); if(this.fade_start) - alph = bound(0, (this.fade_end - vlen(org - this.origin - 0.5 * (this.mins + this.maxs))) / (this.fade_end - this.fade_start), 1); + { + if(vdist(org - this.origin, >, this.fade_end)) + alph = 0; // save on some processing + else if(vdist(org - this.origin, <, this.fade_start)) + alph = 1; // more processing saved + else + alph = bound(0, (this.fade_end - vlen(org - this.origin - 0.5 * (this.mins + this.maxs))) / (this.fade_end - this.fade_start), 1); + } else alph = 1; //printf("%v <-> %v\n", view_origin, this.origin + 0.5 * (this.mins + this.maxs)); @@ -679,10 +699,7 @@ void Spawn_PreDraw(entity this) NET_HANDLE(ENT_CLIENT_SPAWNPOINT, bool is_new) { float teamnum = (ReadByte() - 1); - vector spn_origin; - spn_origin.x = ReadCoord(); - spn_origin.y = ReadCoord(); - spn_origin.z = ReadCoord(); + vector spn_origin = ReadVector(); this.team = (teamnum + 1); @@ -739,9 +756,7 @@ NET_HANDLE(ENT_CLIENT_SPAWNEVENT, bool is_new) if(entnum) { - this.origin_x = ReadCoord(); - this.origin_y = ReadCoord(); - this.origin_z = ReadCoord(); + this.origin = ReadVector(); if(is_new) { @@ -786,7 +801,7 @@ NET_HANDLE(ENT_CLIENT_SPAWNEVENT, bool is_new) // The only parameter reflects if the entity is "new" to the client, meaning it just came into the client's PVS. void CSQC_Ent_Update(entity this, bool isnew) { - this.sourceLoc = __FILE__ ":" STR(__LINE__); + this.sourceLoc = __FILE__":"STR(__LINE__); int t = ReadByte(); // set up the "time" global for received entities to be correct for interpolation purposes @@ -807,7 +822,7 @@ void CSQC_Ent_Update(entity this, bool isnew) { if (t != this.enttype || isnew) { - LOG_INFOF("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", etof(this), this.entnum, this.enttype, t); + LOG_INFOF("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)", etof(this), this.entnum, this.enttype, t); Ent_Remove(this); clearentity(this); isnew = true; @@ -817,7 +832,7 @@ void CSQC_Ent_Update(entity this, bool isnew) { if (!isnew) { - LOG_INFOF("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", etof(this), this.entnum, t); + LOG_INFOF("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)", etof(this), this.entnum, t); isnew = true; } } @@ -827,7 +842,7 @@ void CSQC_Ent_Update(entity this, bool isnew) FOREACH(LinkedEntities, it.m_id == t, { if (isnew) this.classname = it.netname; if (autocvar_developer_csqcentities) - LOG_INFOF("CSQC_Ent_Update(%d) at %f with this=%i {.entnum=%d, .enttype=%d} t=%s (%d)\n", isnew, savetime, this, this.entnum, this.enttype, this.classname, t); + LOG_INFOF("CSQC_Ent_Update(%d) at %f with this=%i {.entnum=%d, .enttype=%d} t=%s (%d)", isnew, savetime, this, this.entnum, this.enttype, this.classname, t); done = it.m_read(this, NULL, isnew); MUTATOR_CALLHOOK(Ent_Update, this, isnew); break; @@ -867,7 +882,7 @@ void Ent_Remove(entity this) // CSQC_Ent_Remove : Called when the server requests a SSQC / CSQC entity to be removed. Essentially call remove(this) as well. void CSQC_Ent_Remove(entity this) { - if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Ent_Remove() with this=%i {.entnum=%d, .enttype=%d}\n", this, this.entnum, this.enttype); + if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Ent_Remove() with this=%i {.entnum=%d, .enttype=%d}", this, this.entnum, this.enttype); if (wasfreed(this)) { LOG_WARN("CSQC_Ent_Remove called for already removed entity. Packet loss?"); @@ -889,20 +904,20 @@ void Gamemode_Init() // CSQC_Parse_StuffCmd : Provides the stuffcmd string in the first parameter that the server provided. To execute standard behavior, simply execute localcmd with the string. void CSQC_Parse_StuffCmd(string strMessage) { - if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_StuffCmd(\"%s\")\n", strMessage); + if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_StuffCmd(\"%s\")", strMessage); localcmd(strMessage); } // CSQC_Parse_Print : Provides the print string in the first parameter that the server provided. To execute standard behavior, simply execute print with the string. void CSQC_Parse_Print(string strMessage) { - if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_Print(\"%s\")\n", strMessage); + if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_Print(\"%s\")", strMessage); print(ColorTranslateRGB(strMessage)); } // CSQC_Parse_CenterPrint : Provides the centerprint_hud string in the first parameter that the server provided. void CSQC_Parse_CenterPrint(string strMessage) { - if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_CenterPrint(\"%s\")\n", strMessage); + if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_CenterPrint(\"%s\")", strMessage); centerprint_hud(strMessage); } @@ -916,12 +931,12 @@ bool CSQC_Parse_TempEntity() FOREACH(TempEntities, it.m_id == nTEID, { if (autocvar_developer_csqcentities) - LOG_INFOF("CSQC_Parse_TempEntity() nTEID=%s (%d)\n", it.netname, nTEID); + LOG_INFOF("CSQC_Parse_TempEntity() nTEID=%s (%d)", it.netname, nTEID); return it.m_read(NULL, NULL, true); }); if (autocvar_developer_csqcentities) - LOG_INFOF("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID); + LOG_INFOF("CSQC_Parse_TempEntity() with nTEID=%d", nTEID); // No special logic for this temporary entity; return 0 so the engine can handle it return false; @@ -936,7 +951,6 @@ void Fog_Force() localcmd(sprintf("\nfog %s\nr_fog_exp2 0\nr_drawfog 1\n", forcefog)); } -void Gamemode_Init(); NET_HANDLE(ENT_CLIENT_SCORES_INFO, bool isnew) { make_pure(this); @@ -944,14 +958,12 @@ NET_HANDLE(ENT_CLIENT_SCORES_INFO, bool isnew) teamplay = _MapInfo_GetTeamPlayBool(gametype); HUD_ModIcons_SetFunc(); FOREACH(Scores, true, { - if (scores_label(it)) strunzone(scores_label(it)); - scores_label(it) = strzone(ReadString()); + strcpy(scores_label(it), ReadString()); scores_flags(it) = ReadByte(); }); for (int i = 0; i < MAX_TEAMSCORE; ++i) { - if (teamscores_label(i)) strunzone(teamscores_label(i)); - teamscores_label(i) = strzone(ReadString()); + strcpy(teamscores_label(i), ReadString()); teamscores_flags(i) = ReadByte(); } return = true; @@ -972,8 +984,7 @@ NET_HANDLE(ENT_CLIENT_INIT, bool isnew) arc_shotorigin[2] = decompressShotOrigin(ReadInt24_t()); arc_shotorigin[3] = decompressShotOrigin(ReadInt24_t()); - if (forcefog) strunzone(forcefog); - forcefog = strzone(ReadString()); + strcpy(forcefog, ReadString()); armorblockpercent = ReadByte() / 255.0; damagepush_speedfactor = ReadByte() / 255.0; @@ -1036,17 +1047,15 @@ NET_HANDLE(TE_CSQC_RACE, bool isNew) race_time = ReadInt24_t(); race_previousbesttime = ReadInt24_t(); race_mypreviousbesttime = ReadInt24_t(); - if(race_previousbestname) - strunzone(race_previousbestname); string pbestname = ReadString(); if(autocvar_cl_race_cptimes_onlyself) { race_previousbesttime = race_mypreviousbesttime; race_mypreviousbesttime = 0; - race_previousbestname = strzone(""); + strcpy(race_previousbestname, ""); } else - race_previousbestname = strzone(pbestname); + strcpy(race_previousbestname, pbestname); race_checkpointtime = time; @@ -1072,17 +1081,15 @@ NET_HANDLE(TE_CSQC_RACE, bool isNew) race_nextbesttime = ReadInt24_t(); if(b != RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING) // not while spectating (matches server) race_mybesttime = ReadInt24_t(); - if(race_nextbestname) - strunzone(race_nextbestname); string newname = ReadString(); if(autocvar_cl_race_cptimes_onlyself && b != RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING) { race_nextbesttime = race_mybesttime; race_mybesttime = 0; - race_nextbestname = strzone(""); + strcpy(race_nextbestname, ""); } else - race_nextbestname = strzone(newname); + strcpy(race_nextbestname, newname); break; case RACE_NET_CHECKPOINT_HIT_RACE: @@ -1092,13 +1099,11 @@ NET_HANDLE(TE_CSQC_RACE, bool isNew) race_mycheckpointlapsdelta = ReadByte(); if(race_mycheckpointlapsdelta >= 128) race_mycheckpointlapsdelta -= 256; - if(race_mycheckpointenemy) - strunzone(race_mycheckpointenemy); int who = ReadByte(); if(who) - race_mycheckpointenemy = strzone(entcs_GetName(who - 1)); + strcpy(race_mycheckpointenemy, entcs_GetName(who - 1)); else - race_mycheckpointenemy = strzone(""); // TODO: maybe string_null works fine here? + strcpy(race_mycheckpointenemy, ""); // TODO: maybe string_null works fine here? break; case RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT: @@ -1108,31 +1113,23 @@ NET_HANDLE(TE_CSQC_RACE, bool isNew) race_othercheckpointlapsdelta = ReadByte(); if(race_othercheckpointlapsdelta >= 128) race_othercheckpointlapsdelta -= 256; - if(race_othercheckpointenemy) - strunzone(race_othercheckpointenemy); int what = ReadByte(); if(what) - race_othercheckpointenemy = strzone(entcs_GetName(what - 1)); + strcpy(race_othercheckpointenemy, entcs_GetName(what - 1)); else - race_othercheckpointenemy = strzone(""); // TODO: maybe string_null works fine here? + strcpy(race_othercheckpointenemy, ""); // TODO: maybe string_null works fine here? break; case RACE_NET_PENALTY_RACE: - race_penaltyeventtime = time; - race_penaltytime = ReadShort(); - //race_penaltyaccumulator += race_penaltytime; - if(race_penaltyreason) - strunzone(race_penaltyreason); - race_penaltyreason = strzone(ReadString()); - break; - case RACE_NET_PENALTY_QUALIFYING: race_penaltyeventtime = time; race_penaltytime = ReadShort(); - race_penaltyaccumulator += race_penaltytime; - if(race_penaltyreason) - strunzone(race_penaltyreason); - race_penaltyreason = strzone(ReadString()); + string reason = ReadString(); + if (reason == "missing a checkpoint") + reason = _("missing a checkpoint"); + strcpy(race_penaltyreason, reason); + if (b == RACE_NET_PENALTY_QUALIFYING) + race_penaltyaccumulator += race_penaltytime; break; case RACE_NET_SERVER_RECORD: @@ -1140,74 +1137,64 @@ NET_HANDLE(TE_CSQC_RACE, bool isNew) break; case RACE_NET_SPEED_AWARD: race_speedaward = ReadInt24_t() * GetSpeedUnitFactor(autocvar_hud_panel_physics_speed_unit); - if(race_speedaward_holder) - strunzone(race_speedaward_holder); - race_speedaward_holder = strzone(ReadString()); - if(race_speedaward_unit) - strunzone(race_speedaward_unit); - race_speedaward_unit = strzone(GetSpeedUnit(autocvar_hud_panel_physics_speed_unit)); + strcpy(race_speedaward_holder, ReadString()); + strcpy(race_speedaward_unit, GetSpeedUnit(autocvar_hud_panel_physics_speed_unit)); break; case RACE_NET_SPEED_AWARD_BEST: race_speedaward_alltimebest = ReadInt24_t() * GetSpeedUnitFactor(autocvar_hud_panel_physics_speed_unit); - if(race_speedaward_alltimebest_holder) - strunzone(race_speedaward_alltimebest_holder); - race_speedaward_alltimebest_holder = strzone(ReadString()); - if(race_speedaward_alltimebest_unit) - strunzone(race_speedaward_alltimebest_unit); - race_speedaward_alltimebest_unit = strzone(GetSpeedUnit(autocvar_hud_panel_physics_speed_unit)); + strcpy(race_speedaward_alltimebest_holder, ReadString()); + strcpy(race_speedaward_alltimebest_unit, GetSpeedUnit(autocvar_hud_panel_physics_speed_unit)); + break; + case RACE_NET_RANKINGS_CNT: + RANKINGS_DISPLAY_CNT = ReadByte(); break; case RACE_NET_SERVER_RANKINGS: float prevpos, del; - int pos = ReadShort(); + int pos = ReadShort(); prevpos = ReadShort(); del = ReadShort(); // move other rankings out of the way - int i; + int i; if (prevpos) { - for (i=prevpos-1;i>pos-1;--i) { + int m = min(prevpos, RANKINGS_DISPLAY_CNT); + for (i=m-1; i>pos-1; --i) { grecordtime[i] = grecordtime[i-1]; - if(grecordholder[i]) - strunzone(grecordholder[i]); - grecordholder[i] = strzone(grecordholder[i-1]); + strcpy(grecordholder[i], grecordholder[i-1]); } } else if (del) { // a record has been deleted by the admin - for (i=pos-1; i<= RANKINGS_CNT-1; ++i) { - if (i == RANKINGS_CNT-1) { // clear out last record + for (i=pos-1; i<= RANKINGS_DISPLAY_CNT-1; ++i) { + if (i == RANKINGS_DISPLAY_CNT-1) { // clear out last record grecordtime[i] = 0; - if (grecordholder[i]) - strunzone(grecordholder[i]); - grecordholder[i] = string_null; + strfree(grecordholder[i]); } else { grecordtime[i] = grecordtime[i+1]; - if (grecordholder[i]) - strunzone(grecordholder[i]); - grecordholder[i] = strzone(grecordholder[i+1]); + strcpy(grecordholder[i], grecordholder[i+1]); } } } else { // player has no ranked record yet - for (i=RANKINGS_CNT-1;i>pos-1;--i) { + for (i=RANKINGS_DISPLAY_CNT-1;i>pos-1;--i) { grecordtime[i] = grecordtime[i-1]; - if(grecordholder[i]) - strunzone(grecordholder[i]); - grecordholder[i] = strzone(grecordholder[i-1]); + strcpy(grecordholder[i], grecordholder[i-1]); } } + if (grecordtime[RANKINGS_DISPLAY_CNT]) { + // kick off the player who fell from the last displayed position + grecordtime[RANKINGS_DISPLAY_CNT] = 0; + strfree(grecordholder[RANKINGS_DISPLAY_CNT]); + } + // store new ranking - if(grecordholder[pos-1] != "") - strunzone(grecordholder[pos-1]); - grecordholder[pos-1] = strzone(ReadString()); + strcpy(grecordholder[pos-1], ReadString()); grecordtime[pos-1] = ReadInt24_t(); if(strdecolorize(grecordholder[pos-1]) == strdecolorize(entcs_GetName(player_localnum))) race_myrank = pos; break; case RACE_NET_SERVER_STATUS: race_status = ReadShort(); - if(race_status_name) - strunzone(race_status_name); - race_status_name = strzone(ReadString()); + strcpy(race_status_name, ReadString()); } return true; } @@ -1234,7 +1221,8 @@ NET_HANDLE(TE_CSQC_PINGPLREPORT, bool isNew) NET_HANDLE(TE_CSQC_WEAPONCOMPLAIN, bool isNew) { - complain_weapon = ReadByte(); + int weapon_id = ReadByte(); + complain_weapon = Weapons_from(weapon_id); complain_weapon_type = ReadByte(); return = true; @@ -1243,9 +1231,9 @@ NET_HANDLE(TE_CSQC_WEAPONCOMPLAIN, bool isNew) switch(complain_weapon_type) { - case 0: Local_Notification(MSG_MULTI, ITEM_WEAPON_NOAMMO, complain_weapon); break; - case 1: Local_Notification(MSG_MULTI, ITEM_WEAPON_DONTHAVE, complain_weapon); break; - default: Local_Notification(MSG_MULTI, ITEM_WEAPON_UNAVAILABLE, complain_weapon); break; + case 0: Local_Notification(MSG_MULTI, ITEM_WEAPON_NOAMMO, weapon_id); break; + case 1: Local_Notification(MSG_MULTI, ITEM_WEAPON_DONTHAVE, weapon_id); break; + default: Local_Notification(MSG_MULTI, ITEM_WEAPON_UNAVAILABLE, weapon_id); break; } } @@ -1271,6 +1259,8 @@ string _getcommandkey(string cmd_name, string command, bool forcename) if(!joy_active && substring(key, 0, 3) == "JOY") continue; + key = translate_key(key); + if (keys == "") keys = key; else