From: Rudolf Polzer Date: Wed, 3 Nov 2010 20:42:30 +0000 (+0100) Subject: Merge remote branch 'refs/remotes/origin/fruitiex/racefixes' X-Git-Tag: xonotic-v0.1.0preview~202 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=4fc59bbd7e2d4f25ba21952ed50ae754295a7faa;hp=3024309e2c0576552bfb2da02ba513662c997768 Merge remote branch 'refs/remotes/origin/fruitiex/racefixes' Conflicts: defaultXonotic.cfg qcsrc/server/defs.qh --- diff --git a/defaultXonotic.cfg b/defaultXonotic.cfg index 84157c2bf7..b340e5ddec 100644 --- a/defaultXonotic.cfg +++ b/defaultXonotic.cfg @@ -630,8 +630,9 @@ set g_ons_respawn_waves 0 set g_rc_respawn_waves 0 set g_rc_respawn_delay 0 set g_cts_respawn_waves 0 -set g_cts_respawn_delay 0 +set g_cts_respawn_delay 0.25 set g_cts_selfdamage 1 "0 = disable all selfdamage and falldamage in cts" +set g_cts_finish_kill_delay 10 "prevent cheating by running back to the start line, and starting out with more speed than otherwise possible" // overtime seta timelimit_overtime 2 "duration in minutes of one added overtime, added to the timelimit" @@ -1657,6 +1658,7 @@ set g_showweaponspawns 1 "display sprites for weapon spawns found on the map whe alias records "cmd records" alias rankings "cmd rankings" +alias ladder "cmd ladder" // ballistics use physical units, but qu based // Quake-Newton: 1 qN = 1 qu * 1 g / 1 s^2 @@ -2001,3 +2003,6 @@ r_font_size_snapping 2 // database management set sv_db_saveasdump 0 "write server.db in dump format (loads slower, easier to read/parse)" set cl_db_saveasdump 0 "write client.db in dump format (loads slower, easier to read/parse)" + +// uid2name +seta cl_allow_uid2name -1 "-1 = ask if the player wants to disable/enable this feature, 0 = disable, 1 = enable uid2name (allows showing your name in race rankings for instance)" diff --git a/qcsrc/client/Main.qc b/qcsrc/client/Main.qc index 9c50d7a344..4846a9fef5 100644 --- a/qcsrc/client/Main.qc +++ b/qcsrc/client/Main.qc @@ -627,6 +627,56 @@ float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary) local float bSkipKey; bSkipKey = false; + if(autocvar_cl_allow_uid2name == -1 && (gametype == GAME_CTS || gametype == GAME_RACE) && panel_fg_alpha && !scoreboard_active) // don't lock keys before we actually see what's going on + { + /* + string vyes_keys; + float keys; + vyes_keys = findkeysforcommand("vyes"); + keys = tokenize(vyes_keys); + + float i; + for (i = 0; i < keys; ++i) + { + print(ftos(nPrimary), " ", argv(i), "\n"); + if(nPrimary == stof(argv(i))) + { + vote_active = 0; + cvar_set("cl_allow_uid2name", "1"); + return TRUE; + } + } + + string vno_keys; + vno_keys = findkeysforcommand("vno"); + keys = tokenize(vno_keys); + + float i; + for (i = 0; i < keys; ++i) + { + if(nPrimary == stof(argv(i))) + { + vote_active = 0; + cvar_set("cl_allow_uid2name", "0"); + return TRUE; + } + } + */ // If only I could grab F1-F12 in CSQC... but no + + if(nPrimary == 121) // ascii value for y + { + vote_active = 0; + cvar_set("cl_allow_uid2name", "1"); + return TRUE; + } + else if(nPrimary == 110) // ascii value for n + { + vote_active = 0; + cvar_set("cl_allow_uid2name", "0"); + return TRUE; + } + } + if (HUD_Panel_InputEvent(bInputType, nPrimary, nSecondary)) return true; @@ -636,6 +686,7 @@ float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary) if(menu_visible) if(menu_action(bInputType, nPrimary, nSecondary)) return TRUE; + return bSkipKey; } diff --git a/qcsrc/client/autocvars.qh b/qcsrc/client/autocvars.qh index ac721eda1a..ea0fcecedf 100644 --- a/qcsrc/client/autocvars.qh +++ b/qcsrc/client/autocvars.qh @@ -235,3 +235,5 @@ var string autocvar_hud_panel_infomessages_bg_padding; var float autocvar_hud_panel_infomessages_flip; var float autocvar_scoreboard_border_thickness; + +var float autocvar_cl_allow_uid2name; diff --git a/qcsrc/client/hud.qc b/qcsrc/client/hud.qc index 379b810751..971a791aad 100644 --- a/qcsrc/client/hud.qc +++ b/qcsrc/client/hud.qc @@ -2595,6 +2595,9 @@ void HUD_KillNotify(string s1, string s2, string s3, float type, float msg) // s alsoprint = (autocvar_hud_panel_notify_print || !panel_enabled); // print message to console if: notify panel disabled, or cvar to do so enabled gentle = (autocvar_cl_gentle || autocvar_cl_gentle_messages); + if ((msg == MSG_SUICIDE || msg == MSG_KILL || msg == MSG_KILL_ACTION) && gametype == GAME_CTS) // selfkill isn't interesting in CTS and only spams up the notify panel + return; + if(msg == MSG_SUICIDE) { w = DEATH_WEAPONOF(type); if(WEP_VALID(w)) { @@ -2921,6 +2924,19 @@ void HUD_KillNotify(string s1, string s2, string s3, float type, float msg) // s HUD_KillNotify_Push(s1, s2, 0, INFO_CAPTUREFLAG); print(s1, "^7 captured the ", s2, s3, "\n"); } + } else if(msg == MSG_RACE) { + if(type == RACE_SERVER_RECORD) { + HUD_KillNotify_Push(s1, s2, 1, RACE_SERVER_RECORD); + } + else if(type == RACE_NEW_RANK) { + HUD_KillNotify_Push(s1, s2, 1, RACE_NEW_RANK); + } + else if(type == RACE_NEW_TIME) { + HUD_KillNotify_Push(s1, s2, 1, RACE_NEW_TIME); + } + else if(type == RACE_FAIL) { + HUD_KillNotify_Push(s1, s2, 1, RACE_FAIL); + } } } @@ -3257,6 +3273,22 @@ void HUD_Notify (void) { s = "notify_void"; } + else if(killnotify_deathtype[j] == RACE_SERVER_RECORD) + { + s = "race_newrecordserver"; + } + else if(killnotify_deathtype[j] == RACE_NEW_RANK) + { + s = "race_newrankyellow"; + } + else if(killnotify_deathtype[j] == RACE_NEW_TIME) + { + s = "race_newtime"; + } + else if(killnotify_deathtype[j] == RACE_FAIL) + { + s = "race_newfail"; + } if(s != "" && a) { drawpic_aspect_skin(weap_pos, s, '2 1 0' * height, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); @@ -3485,6 +3517,7 @@ void HUD_Score(void) } float score, distribution, leader; + string sign; vector distribution_color; entity tm, pl, me; me = (spectatee_status > 0) ? playerslots[spectatee_status - 1] : playerslots[player_localentnum - 1]; @@ -3506,15 +3539,17 @@ void HUD_Score(void) // distribution display distribution = me.(scores[ps_primary]) - pl.(scores[ps_primary]); - distrtimer = ftos(distribution/pow(10, TIME_DECIMALS)); + distrtimer = ftos_decimals(fabs(distribution/pow(10, TIME_DECIMALS)), TIME_DECIMALS); if (distribution <= 0) { distribution_color = '0 1 0'; + sign = "-"; } else { distribution_color = '1 0 0'; + sign = "+"; } - drawstring_aspect(pos + eX * 0.75 * mySize_x, distrtimer, eX * 0.25 * mySize_x + eY * (1/3) * mySize_y, distribution_color, panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring_aspect(pos + eX * 0.75 * mySize_x, strcat(sign, distrtimer), eX * 0.25 * mySize_x + eY * (1/3) * mySize_y, distribution_color, panel_fg_alpha, DRAWFLAG_NORMAL); } // race record display if (distribution <= 0) @@ -3747,11 +3782,22 @@ float vote_change; // "time" when vote_active changed void HUD_VoteWindow(void) { + if(autocvar_cl_allow_uid2name == -1 && (gametype == GAME_CTS || gametype == GAME_RACE)) + { + vote_active = 1; + vote_called_vote = strzone(strcat("^2Name ^7instead of \"^1Unregistered player\"", " ^7in stats")); + } + if(!autocvar_hud_panel_vote && !autocvar__hud_configure) return; active_panel = HUD_PANEL_VOTE; HUD_Panel_UpdateCvars(vote); + if(autocvar_cl_allow_uid2name == -1 && (gametype == GAME_CTS || gametype == GAME_RACE)) + { + panel_pos = eX * 0.3 * vid_conwidth + eY * 0.1 * vid_conheight; + panel_size = eX * 0.4 * vid_conwidth + eY * 0.3 * vid_conheight; + } vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -3817,16 +3863,22 @@ void HUD_VoteWindow(void) mySize = newSize; s = "A vote has been called for:"; + if(autocvar_cl_allow_uid2name == -1 && (gametype == GAME_CTS || gametype == GAME_RACE)) + s = "Allow servers to store and display your name?"; drawstring_aspect(pos, s, eX * mySize_x + eY * (2/8) * mySize_y, '1 1 1', a, DRAWFLAG_NORMAL); - s = textShortenToWidth(vote_called_vote, mySize_x, '1 1 0' * mySize_y * (1.75/8), stringwidth_colors); + s = textShortenToWidth(vote_called_vote, mySize_x, '1 1 0' * mySize_y * (1/8), stringwidth_colors); if(autocvar__hud_configure) s = "^1Configure the HUD"; drawcolorcodedstring_aspect(pos + eY * (2/8) * mySize_y, s, eX * mySize_x + eY * (1.75/8) * mySize_y, a, DRAWFLAG_NORMAL); // print the yes/no counts s = strcat("Yes (", getcommandkey("vyes", "vyes"), "): ", ftos(vote_yescount)); + if(autocvar_cl_allow_uid2name == -1 && (gametype == GAME_CTS || gametype == GAME_RACE)) + s = strcat("Yes: (press y)"); drawstring_aspect(pos + eY * (4/8) * mySize_y, s, eX * 0.5 * mySize_x + eY * (1.5/8) * mySize_y, '0 1 0', a, DRAWFLAG_NORMAL); s = strcat("No (", getcommandkey("vno", "vno"), "): ", ftos(vote_nocount)); + if(autocvar_cl_allow_uid2name == -1 && (gametype == GAME_CTS || gametype == GAME_RACE)) + s = strcat("No: (press n)"); drawstring_aspect(pos + eX * 0.5 * mySize_x + eY * (4/8) * mySize_y, s, eX * 0.5 * mySize_x + eY * (1.5/8) * mySize_y, '1 0 0', a, DRAWFLAG_NORMAL); // draw the progress bar backgrounds diff --git a/qcsrc/client/scoreboard.qc b/qcsrc/client/scoreboard.qc index 2fdf0d2203..b61568a2ae 100644 --- a/qcsrc/client/scoreboard.qc +++ b/qcsrc/client/scoreboard.qc @@ -1043,7 +1043,7 @@ vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_ pos_y += hud_fontsize_y; vector tmp; tmp_x = sbwidth; - tmp_y = hud_fontsize_y * RANKINGS_RECEIVED_CNT; + tmp_y = 1.25 * hud_fontsize_y * RANKINGS_RECEIVED_CNT; if (teamplay) drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL); @@ -1062,12 +1062,12 @@ vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_ n = grecordholder[i]; p = race_PlaceName(i+1); if(grecordholder[i] == GetPlayerName(player_localentnum - 1)) - drawfill(pos, '1 0 0' * sbwidth + '0 1 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL); + drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL); else if(!mod(i, 2) && scoreboard_highlight) - drawfill(pos, '1 0 0' * sbwidth + '0 1 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL); - drawstring(pos, p, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL); - drawstring(pos + '3 0 0' * hud_fontsize_x, TIME_ENCODED_TOSTRING(t), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL); - drawcolorcodedstring(pos + '8 0 0' * hud_fontsize_x, n, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL); + drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL); + drawstring(pos, p, '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL); + drawstring(pos + '3 0 0' * hud_fontsize_y, TIME_ENCODED_TOSTRING(t), '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL); + drawcolorcodedstring(pos + '8 0 0' * hud_fontsize_y, n, '1 1 0' * hud_fontsize_y, scoreboard_alpha_fg, DRAWFLAG_NORMAL); pos_y += 1.25 * hud_fontsize_y; } @@ -1176,11 +1176,11 @@ void HUD_DrawScoreboard() if(gametype == GAME_CTS || gametype == GAME_RACE) { if(race_speedaward) { - drawcolorcodedstring(pos, strcat("Speed award: ", ftos(race_speedaward), " (", race_speedaward_holder, ")"), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL); + drawcolorcodedstring(pos, strcat("Speed award: ", ftos(race_speedaward), " ^7(", race_speedaward_holder, "^7)"), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL); pos_y += 1.25 * hud_fontsize_y; } if(race_speedaward_alltimebest) { - drawcolorcodedstring(pos, strcat("All-time fastest: ", ftos(race_speedaward_alltimebest), " (", race_speedaward_alltimebest_holder, ")"), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL); + drawcolorcodedstring(pos, strcat("All-time fastest: ", ftos(race_speedaward_alltimebest), " ^7(", race_speedaward_alltimebest_holder, "^7)"), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL); pos_y += 1.25 * hud_fontsize_y; } pos = HUD_DrawScoreboardRankings(pos, pl, rgb, bg_size); diff --git a/qcsrc/common/constants.qh b/qcsrc/common/constants.qh index 36ea68ddd8..29029f6e45 100644 --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@ -565,6 +565,8 @@ float MSG_KILL_ACTION = 3; float MSG_KILL_ACTION_SPREE = 4; float MSG_INFO = 5; +float MSG_RACE = 10; + float KILL_TEAM_RED = 10301; float KILL_TEAM_BLUE = 10302; float KILL_TEAM_SPREE = 10303; @@ -590,6 +592,11 @@ float INFO_LOSTFLAG = 10321; float INFO_RETURNFLAG = 10322; float INFO_CAPTUREFLAG = 10323; +float RACE_SERVER_RECORD = 10400; +float RACE_NEW_TIME = 10401; +float RACE_NEW_RANK = 10402; +float RACE_FAIL = 10403; + // weapon requests float WR_SETUP = 1; // (SVQC) setup weapon data float WR_THINK = 2; // (SVQC) logic to run every frame diff --git a/qcsrc/common/gamecommand.qc b/qcsrc/common/gamecommand.qc index be2f5e78c2..f6b54f155b 100644 --- a/qcsrc/common/gamecommand.qc +++ b/qcsrc/common/gamecommand.qc @@ -831,6 +831,10 @@ float GameCommand_Generic(string command) print(records_reply); return TRUE; } + else if(argv(0) == "ladder") { + print(ladder_reply); + return TRUE; + } else if(argv(0) == "rankings") { print(rankings_reply); return TRUE; diff --git a/qcsrc/common/util.qh b/qcsrc/common/util.qh index f1d283238b..2de439ff27 100644 --- a/qcsrc/common/util.qh +++ b/qcsrc/common/util.qh @@ -165,7 +165,7 @@ void check_unacceptable_compiler_bugs(); float compressShotOrigin(vector v); vector decompressShotOrigin(float f); -string rankings_reply, lsmaps_reply, lsnewmaps_reply, maplist_reply; // cached replies +string rankings_reply, ladder_reply, lsmaps_reply, lsnewmaps_reply, maplist_reply; // cached replies string records_reply[10]; float RandomSelection_totalweight; diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index b03723ae45..66a838a31c 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -1313,6 +1313,22 @@ void ClientKill (void) ClientKill_TeamChange(0); } +void CTS_ClientKill_Think (void) +{ + self = self.owner; // set self to the player to be killed + sprint(self, "^1You were killed in order to prevent cheating!"); + ClientKill_Now(); +} + +void CTS_ClientKill (float t) // silent version of ClientKill +{ + entity e; + e = spawn(); + e.owner = self; + e.think = CTS_ClientKill_Think; + e.nextthink = t; +} + void DoTeamChange(float destteam) { float t, c0; @@ -1587,11 +1603,12 @@ void ClientConnect (void) rr = RACE_RECORD; t = stof(db_get(ServerProgsDB, strcat(GetMapname(), rr, "time"))); + msg_entity = self; race_send_recordtime(MSG_ONE); race_send_speedaward(MSG_ONE); speedaward_alltimebest = stof(db_get(ServerProgsDB, strcat(GetMapname(), rr, "speed/speed"))); - speedaward_alltimebest_holder = db_get(ServerProgsDB, strcat(GetMapname(), rr, "speed/netname")); + speedaward_alltimebest_holder = uid2name(db_get(ServerProgsDB, strcat(GetMapname(), rr, "speed/crypto_idfp"))); race_send_speedaward_alltimebest(MSG_ONE); float i; @@ -3017,6 +3034,18 @@ void PlayerPostThink (void) playerdemo_write(); + if((g_cts || g_race) && self.cvar_cl_allow_uid2name) + { + if(!self.stored_netname) + self.stored_netname = strzone(uid2name(self.crypto_idfp)); + if(self.stored_netname != self.netname) + { + db_put(ServerProgsDB, strcat("uid2name", self.crypto_idfp), self.netname); + strunzone(self.stored_netname); + self.stored_netname = strzone(self.netname); + } + } + /* if(g_race) dprint(sprintf("%f %.6f\n", time, race_GetFractionalLapCount(self))); diff --git a/qcsrc/server/cl_physics.qc b/qcsrc/server/cl_physics.qc index 440c69bf33..e211275b0f 100644 --- a/qcsrc/server/cl_physics.qc +++ b/qcsrc/server/cl_physics.qc @@ -671,6 +671,7 @@ void SpecialCommand() float speedaward_speed; string speedaward_holder; +string speedaward_uid; void race_send_speedaward(float msg) { // send the best speed of the round @@ -683,6 +684,7 @@ void race_send_speedaward(float msg) float speedaward_alltimebest; string speedaward_alltimebest_holder; +string speedaward_alltimebest_uid; void race_send_speedaward_alltimebest(float msg) { // send the best speed @@ -1304,6 +1306,7 @@ void SV_PlayerPhysics() if(vlen(self.velocity - self.velocity_z * '0 0 1') > speedaward_speed) { speedaward_speed = vlen(self.velocity - self.velocity_z * '0 0 1'); speedaward_holder = self.netname; + speedaward_uid = self.crypto_idfp; speedaward_lastupdate = time; } if(speedaward_speed > speedaward_lastsent && time - speedaward_lastupdate > 1) { @@ -1317,8 +1320,9 @@ void SV_PlayerPhysics() if (speedaward_speed > speedaward_alltimebest) { speedaward_alltimebest = speedaward_speed; speedaward_alltimebest_holder = speedaward_holder; + speedaward_alltimebest_uid = speedaward_uid; db_put(ServerProgsDB, strcat(GetMapname(), rr, "speed/speed"), ftos(speedaward_alltimebest)); - db_put(ServerProgsDB, strcat(GetMapname(), rr, "speed/netname"), speedaward_alltimebest_holder); + db_put(ServerProgsDB, strcat(GetMapname(), rr, "speed/crypto_idfp"), speedaward_alltimebest_uid); race_send_speedaward_alltimebest(MSG_ALL); } } diff --git a/qcsrc/server/clientcommands.qc b/qcsrc/server/clientcommands.qc index 0216757e9c..df19ab592f 100644 --- a/qcsrc/server/clientcommands.qc +++ b/qcsrc/server/clientcommands.qc @@ -303,6 +303,8 @@ void SV_ParseClientCommand(string s) { } else if(cmd == "records") { for(i = 0; i < 10; ++i) sprint(self, records_reply[i]); + } else if(cmd == "ladder") { + sprint(self, ladder_reply); } else if(cmd == "rankings") { sprint(self, rankings_reply); } else if(cmd == "voice") { diff --git a/qcsrc/server/defs.qh b/qcsrc/server/defs.qh index ecca4ac431..45394eb792 100644 --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@ -329,6 +329,9 @@ float sv_loddistance2; .string weaponorder_byimpulse; +.float cvar_cl_allow_uid2name; +.string stored_netname; + void Announce(string snd); void AnnounceTo(entity e, string snd); diff --git a/qcsrc/server/g_violence.qc b/qcsrc/server/g_violence.qc index a6e73ba251..f5def6a7dd 100644 --- a/qcsrc/server/g_violence.qc +++ b/qcsrc/server/g_violence.qc @@ -13,6 +13,9 @@ float Violence_GibSplash_SendEntity(entity to, float sf) // TODO maybe convert this to a TE? void Violence_GibSplash_At(vector org, vector dir, float type, float amount, entity gibowner, entity attacker) { + if(g_cts) // no gibs in CTS + return; + entity e; e = spawn(); diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index b24beddd3a..ce7b8e2a15 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -821,6 +821,8 @@ void spawnfunc_worldspawn (void) { records_reply[i] = strzone(getrecords(i)); } + if(g_cts) + ladder_reply = strzone(getladder()); rankings_reply = strzone(getrankings()); diff --git a/qcsrc/server/gamecommand.qc b/qcsrc/server/gamecommand.qc index 9dd7e87848..90b06a5a3d 100644 --- a/qcsrc/server/gamecommand.qc +++ b/qcsrc/server/gamecommand.qc @@ -1,5 +1,5 @@ string GotoMap(string m); -void race_DeleteTime(float pos); +void race_deleteTime(string map, float pos); float FullTraceFraction(vector a, vector mi, vector ma, vector b) { @@ -930,6 +930,11 @@ void GameCommand(string command) print(records_reply[i]); return; } + if (argv(0) == "ladder") + { + print(ladder_reply); + return; + } if (argv(0) == "rankings") { strunzone(rankings_reply); @@ -1346,7 +1351,11 @@ void GameCommand(string command) } if(argv(0) == "delrec") { - race_DeleteTime(stof(argv(1))); + if(argv(2) != "") + race_deleteTime(argv(2), stof(argv(1))); + else + race_deleteTime(GetMapname(), stof(argv(1))); + return; } diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index 668e86f898..a20c31dd63 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -16,9 +16,6 @@ void WarpZone_crosshair_trace(entity pl) void() spawnfunc_info_player_deathmatch; // needed for the other spawnpoints void() spawnpoint_use; -float race_GetTime(float pos); -string race_GetName(float pos); -string race_PlaceName(float pos); string GetMapname(); string ColoredTeamName(float t); @@ -638,6 +635,7 @@ void GetCvars(float f) GetCvars_handleFloat(s, f, cvar_cl_forceplayermodelsfromxonotic, "cl_forceplayermodelsfromxonotic"); #endif GetCvars_handleFloatOnce(s, f, cvar_cl_gunalign, "cl_gunalign"); + GetCvars_handleFloat(s, f, cvar_cl_allow_uid2name, "cl_allow_uid2name"); // fixup of switchweapon (needed for LMS or when spectating is disabled, as PutClientInServer comes too early) if (f > 0) @@ -2078,6 +2076,106 @@ void print_to(entity e, string s) print(s, "\n"); } +string uid2name(string myuid) { + string s; + s = db_get(ServerProgsDB, strcat("uid2name", myuid)); + + if(s == "") + s = "^1Unregistered Player"; + return s; +} + +float race_readTime(string map, float pos) +{ + string rr; + if(g_cts) + rr = CTS_RECORD; + else + rr = RACE_RECORD; + + return stof(db_get(ServerProgsDB, strcat(map, rr, "time", ftos(pos)))); +} + +string race_readUID(string map, float pos) +{ + string rr; + if(g_cts) + rr = CTS_RECORD; + else + rr = RACE_RECORD; + + return db_get(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(pos))); +} + +float race_readPos(string map, float t) { + float i; + for (i = 1; i <= RANKINGS_CNT; ++i) + if (race_readTime(map, i) == 0 || race_readTime(map, i) > t) + return i; + + return 0; // pos is zero if unranked +} + +void race_writeTime(string map, float t, string myuid) +{ + string rr; + if(g_cts) + rr = CTS_RECORD; + else + rr = RACE_RECORD; + + float newpos; + newpos = race_readPos(map, t); + + float i, prevpos; + for(i = 1; i <= RANKINGS_CNT; ++i) + { + if(race_readUID(map, i) == myuid) + prevpos = i; + } + if (prevpos) { // player improved his existing record, only have to iterate on ranks between new and old recs + for (i = prevpos; i > newpos; --i) { + db_put(ServerProgsDB, strcat(map, rr, "time", ftos(i)), ftos(race_readTime(map, i - 1))); + db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(i)), race_readUID(map, i - 1)); + } + } else { // player has no ranked record yet + for (i = RANKINGS_CNT; i > newpos; --i) { + db_put(ServerProgsDB, strcat(map, rr, "time", ftos(i)), ftos(race_readTime(map, i - 1))); + db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(i)), race_readUID(map, i - 1)); + } + } + + // store new time itself + db_put(ServerProgsDB, strcat(map, rr, "time", ftos(newpos)), ftos(t)); + db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(newpos)), myuid); +} + +string race_readName(string map, float pos) +{ + string rr; + if(g_cts) + rr = CTS_RECORD; + else + rr = RACE_RECORD; + + return uid2name(db_get(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(pos)))); +} + +string race_placeName(float pos) { + if(floor((mod(pos, 100))/10) * 10 != 10) // examples: 12th, 111th, 213th will not execute this block + { + if(mod(pos, 10) == 1) + return strcat(ftos(pos), "st"); + else if(mod(pos, 10) == 2) + return strcat(ftos(pos), "nd"); + else if(mod(pos, 10) == 3) + return strcat(ftos(pos), "rd"); + else + return strcat(ftos(pos), "th"); + } + else + return strcat(ftos(pos), "th"); +} string getrecords(float page) // 50 records per page { float rec; @@ -2099,6 +2197,7 @@ string getrecords(float page) // 50 records per page r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/captimerecord/time"))); if (r == 0) continue; + // TODO: uid2name h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/captimerecord/netname")); s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-6, ftos_decimals(r, 2)), " ", h, "\n"); ++rec; @@ -2112,10 +2211,10 @@ string getrecords(float page) // 50 records per page { if (MapInfo_Get_ByID(i)) { - r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, RACE_RECORD, "time"))); + r = race_readTime(MapInfo_Map_bspname, 1); if (r == 0) continue; - h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, RACE_RECORD, "netname")); + h = race_readName(MapInfo_Map_bspname, 1); s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-8, TIME_ENCODED_TOSTRING(r)), " ", h, "\n"); ++rec; } @@ -2128,10 +2227,10 @@ string getrecords(float page) // 50 records per page { if (MapInfo_Get_ByID(i)) { - r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, CTS_RECORD, "time"))); + r = race_readTime(MapInfo_Map_bspname, 1); if (r == 0) continue; - h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, CTS_RECORD, "netname")); + h = race_readName(MapInfo_Map_bspname, 1); s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-8, TIME_ENCODED_TOSTRING(r)), " ", h, "\n"); ++rec; } @@ -2161,11 +2260,11 @@ string getrankings() for (i = 1; i <= RANKINGS_CNT; ++i) { - t = race_GetTime(i); + t = race_readTime(map, i); if (t == 0) continue; - n = race_GetName(i); - p = race_PlaceName(i); + n = race_readName(map, i); + p = race_placeName(i); s = strcat(s, strpad(8, p), " ", strpad(-8, TIME_ENCODED_TOSTRING(t)), " ", n, "\n"); } @@ -2177,6 +2276,189 @@ string getrankings() return strcat("Records for ", map, ":\n", s); } +const float LADDER_FIRSTPOINT = 100; +const float LADDER_CNT = 10; // position X still gives LADDER_FIRSTPOINT/X points +const float LADDER_SIZE = 30; // ladder shows the top X players +string top_uids[LADDER_SIZE]; +float top_scores[LADDER_SIZE]; +string getladder() +{ + float i, j, k, uidcnt; + string s, temp_s; + + s = ""; + temp_s = ""; + + string rr; + if(g_cts) + rr = CTS_RECORD; + else + rr = RACE_RECORD; + + string myuid; + + for (k = 0; k < MapInfo_count; ++k) + { + if (MapInfo_Get_ByID(k)) + { + for (i = 0; i <= LADDER_CNT; ++i) { // i = 0 because it is the speed award + if(i == 0) // speed award + { + if(stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, rr, "speed/speed"))) == 0) + continue; + + myuid = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, rr, "speed/crypto_idfp")); + } + else // normal record, if it exists (else break) + { + if(race_readTime(MapInfo_Map_bspname, i) == 0) + continue; + + myuid = race_readUID(MapInfo_Map_bspname, i); + } + + // string s contains: + // arg 0 = # of speed recs + // arg 1 = # of 1st place recs + // arg 2 = # of 2nd place recs + // ... etc + // LADDER_CNT+1 = total points + + temp_s = db_get(TemporaryDB, strcat("ladder", myuid)); + if (temp_s == "") + { + db_put(TemporaryDB, strcat("uid", ftos(uidcnt)), myuid); + ++uidcnt; + for (j = 0; j <= LADDER_CNT + 1; ++j) + { + if(j != LADDER_CNT + 1) + temp_s = strcat(temp_s, "0 "); + else + temp_s = strcat(temp_s, "0"); + } + } + + tokenize_console(temp_s); + s = ""; + + if(i == 0) // speed award + for (j = 0; j <= LADDER_CNT; ++j) // loop over each arg in the string + { + if(j == 0) // speed award + s = strcat(s, ftos(stof(argv(j)) +1)); // add 1 to speed rec count and write + else + s = strcat(s, " ", argv(j)); // just copy over everything else + } + else // record + for (j = 0; j <= LADDER_CNT; ++j) // loop over each arg in the string + { + if(j == 0) + s = strcat(s, argv(j)); // speed award, dont prefix with " " + else if(j == i) // wanted rec! + s = strcat(s, " ", ftos(stof(argv(j)) +1)); // update argv(j) + else + s = strcat(s, " ", argv(j)); // just copy over everything else + } + + // total points are (by default) calculated like this: + // speedrec = floor(100 / 10) = 10 points + // 1st place = floor(100 / 1) = 100 points + // 2nd place = floor(100 / 2) = 50 points + // 3rd place = floor(100 / 3) = 33 points + // 4th place = floor(100 / 4) = 25 points + // 5th place = floor(100 / 5) = 20 points + // ... etc + + if(i == 0) + s = strcat(s, " ", ftos(stof(argv(LADDER_CNT+1)) + LADDER_FIRSTPOINT / 10)); // speed award, add LADDER_FIRSTPOINT / 10 points + else + s = strcat(s, " ", ftos(stof(argv(LADDER_CNT+1)) + floor(LADDER_FIRSTPOINT / i))); // record, add LADDER_FIRSTPOINT / i points + + db_put(TemporaryDB, strcat("ladder", myuid), s); + } + } + } + + float thiscnt; + string thisuid; + for (i = 0; i <= uidcnt; ++i) // for each known uid + { + thisuid = db_get(TemporaryDB, strcat("uid", ftos(i))); + temp_s = db_get(TemporaryDB, strcat("ladder", thisuid)); + tokenize_console(temp_s); + thiscnt = stof(argv(LADDER_CNT+1)); + + if(thiscnt > top_scores[LADDER_SIZE-1]) + for (j = 0; j < LADDER_SIZE; ++j) // for each place in ladder + { + if(thiscnt > top_scores[j]) + { + for (k = LADDER_SIZE-1; k >= j; --k) + { + top_uids[k] = top_uids[k-1]; + top_scores[k] = top_scores[k-1]; + } + top_uids[j] = thisuid; + top_scores[j] = thiscnt; + break; + } + } + } + + s = "^3-----------------------\n\n"; + + s = strcat(s, "Pos ^3|"); + s = strcat(s, " ^7Total ^3|"); + for (i = 1; i <= LADDER_CNT; ++i) + { + s = strcat(s, " ^7", race_placeName(i), " ^3|"); + } + s = strcat(s, " ^7Speed awards ^3| ^7Name"); + + s = strcat(s, "\n^3----+--------"); + for (i = 1; i <= min(9, LADDER_CNT); ++i) + { + s = strcat(s, "+-----"); + } + if(LADDER_CNT > 9) + for (i = 1; i <= LADDER_CNT - 9; ++i) + { + s = strcat(s, "+------"); + } + + s = strcat(s, "+--------------+--------------------\n"); + + for (i = 0; i < LADDER_SIZE; ++i) + { + temp_s = db_get(TemporaryDB, strcat("ladder", top_uids[i])); + tokenize_console(temp_s); + if (argv(LADDER_CNT+1) == "") // total is 0, skip + continue; + s = strcat(s, strpad(4, race_placeName(i+1)), "^3| ^7"); // pos + s = strcat(s, strpad(7, argv(LADDER_CNT+1)), "^3| ^7"); // total + for (j = 1; j <= min(9, LADDER_CNT); ++j) + { + s = strcat(s, strpad(4, argv(j)), "^3| ^7"); // 1st, 2nd, 3rd etc cnt + } + if(LADDER_CNT > 9) + for (j = 10; j <= LADDER_CNT; ++j) + { + s = strcat(s, strpad(4, argv(j)), " ^3| ^7"); // 1st, 2nd, 3rd etc cnt + } + + s = strcat(s, strpad(13, argv(0)), "^3| ^7"); // speed award cnt + s = strcat(s, uid2name(top_uids[i]), "\n"); // name + } + + MapInfo_ClearTemps(); + + if (s == "") + return "No ladder on this server!\n"; + else + return strcat("Top ", ftos(LADDER_SIZE), " ladder rankings:\n", s); +} + + float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance) { float m, i; diff --git a/qcsrc/server/race.qc b/qcsrc/server/race.qc index 2f15889819..3786edbe51 100644 --- a/qcsrc/server/race.qc +++ b/qcsrc/server/race.qc @@ -98,75 +98,13 @@ void race_InitSpectator() race_SendNextCheckpoint(msg_entity.enemy, 1); } -string rr; -float grecordtime[RANKINGS_CNT]; -string grecordholder[RANKINGS_CNT]; -string grecorduid[RANKINGS_CNT]; -float worst_time; // last ranked time -float have_recs; // have we already read the records from the database before? -float race_GetTime(float pos) { - if(g_cts) - rr = CTS_RECORD; - else - rr = RACE_RECORD; - - if (!have_recs) { // I guess this is better than checking if the first array item is empty, rumor has it that arrays are slow - float i; - for(i=0;i= once before - return grecordholder[pos-1]; -} - -float race_CheckUID(string myuid, string net_name) { // return existing UID or player name ranking pos, else 0 - float i; - if(myuid) - { - for (i=RANKINGS_CNT-1;i>=0;--i) - if(grecorduid[i] == myuid) - return i+1; - } - for (i=RANKINGS_CNT-1;i>=0;--i) - if(!grecorduid[i]) - if(grecordholder[i] == net_name) - return i+1; - return 0; -} - -float race_GetPos(float t) { - float i; - - if(worst_time == 0) - for (i=0;i t) - return i+1; - - for (i=0;i t) - return i+1; - return 0; -} - void race_send_recordtime(float msg) { // send the server best time WriteByte(msg, SVC_TEMPENTITY); WriteByte(msg, TE_CSQC_RACE); WriteByte(msg, RACE_NET_SERVER_RECORD); - WriteInt24_t(msg, race_GetTime(1)); + WriteInt24_t(msg, race_readTime(GetMapname(), 1)); } void race_SendRankings(float pos, float prevpos, float del, float msg) @@ -177,8 +115,8 @@ void race_SendRankings(float pos, float prevpos, float del, float msg) WriteShort(msg, pos); WriteShort(msg, prevpos); WriteShort(msg, del); - WriteString(msg, race_GetName(pos)); - WriteInt24_t(msg, race_GetTime(pos)); + WriteString(msg, race_readName(GetMapname(), pos)); + WriteInt24_t(msg, race_readTime(GetMapname(), pos)); } void race_SendStatus(float id, entity e) @@ -198,179 +136,99 @@ void race_SendStatus(float id, entity e) }); } -string race_PlaceName(float pos) { - if(pos == 1) - return "1st"; - else if(pos == 2) - return "2nd"; - else if(pos == 3) - return "3rd"; - else - return strcat(ftos(pos), "th"); -} +void race_setTime(string map, float t, string myuid, string mynetname, entity e) { // netname only used TEMPORARILY for printing + float newpos, player_prevpos; + newpos = race_readPos(map, t); -void race_SetTime(entity e, float t, float match_rec) { - float pos, prevpos; - pos = race_GetPos(t); - prevpos = race_CheckUID(e.crypto_idfp, e.netname); + float i; + for(i = 1; i <= RANKINGS_CNT; ++i) + { + if(race_readUID(map, i) == myuid) + player_prevpos = i; + } float oldrec; - string recorddifference; - if (prevpos && (prevpos < pos || !pos)) + string recorddifference, oldrec_holder; + if (player_prevpos && (player_prevpos < newpos || !newpos)) { - oldrec = race_GetTime(prevpos); + oldrec = race_readTime(GetMapname(), player_prevpos); recorddifference = strcat(" ^1[+", TIME_ENCODED_TOSTRING(t - oldrec), "]"); - bprint(e.netname, "^7 couldn't break their ", race_PlaceName(prevpos), " place record of ", TIME_ENCODED_TOSTRING(oldrec), recorddifference, "\n"); + bprint(mynetname, "^7 couldn't break their ", race_placeName(player_prevpos), " place record of ", TIME_ENCODED_TOSTRING(oldrec), recorddifference, "\n"); race_SendStatus(0, e); // "fail" + Send_KillNotification(e.netname, TIME_ENCODED_TOSTRING(t), "", RACE_FAIL, MSG_RACE); return; - } else if (!pos) { // no ranking, time worse than the worst ranked - recorddifference = strcat(" ^1[+", TIME_ENCODED_TOSTRING(t - grecordtime[RANKINGS_CNT-1]), "]"); - bprint(e.netname, "^7 couldn't break the ", race_PlaceName(RANKINGS_CNT), " place record of ", TIME_ENCODED_TOSTRING(grecordtime[RANKINGS_CNT-1]), recorddifference, "\n"); + } else if (!newpos) { // no ranking, time worse than the worst ranked + recorddifference = strcat(" ^1[+", TIME_ENCODED_TOSTRING(t - race_readTime(GetMapname(), RANKINGS_CNT)), "]"); + bprint(mynetname, "^7 couldn't break the ", race_placeName(RANKINGS_CNT), " place record of ", TIME_ENCODED_TOSTRING(race_readTime(GetMapname(), RANKINGS_CNT)), recorddifference, "\n"); race_SendStatus(0, e); // "fail" + Send_KillNotification(e.netname, TIME_ENCODED_TOSTRING(t), "", RACE_FAIL, MSG_RACE); return; } - oldrec = grecordtime[pos-1]; + // if we didn't hit a return yet, we have a new record! - // move other rankings out of the way - float i; - if (prevpos) { // player improved his existing record - for (i=prevpos-1;i>pos-1;--i) { - db_put(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(i)), ftos(grecordtime[i-1])); - db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(i)), grecordholder[i-1]); - db_put(ServerProgsDB, strcat(GetMapname(), rr, "crypto_idfp", ftos(i)), grecorduid[i-1]); - grecordtime[i] = grecordtime[i-1]; - - if (grecordholder[i]) - strunzone(grecordholder[i]); - grecordholder[i] = strzone(grecordholder[i-1]); - if (grecorduid[i]) - strunzone(grecorduid[i]); - grecorduid[i] = strzone(grecorduid[i-1]); - } - } else { // player has no ranked record yet - for (i=RANKINGS_CNT-1;i>pos-1;--i) { - db_put(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(i)), ftos(grecordtime[i-1])); - db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(i)), grecordholder[i-1]); - db_put(ServerProgsDB, strcat(GetMapname(), rr, "crypto_idfp", ftos(i)), grecorduid[i-1]); - grecordtime[i] = grecordtime[i-1]; - - if (grecordholder[i]) - strunzone(grecordholder[i]); - grecordholder[i] = strzone(grecordholder[i-1]); - if (grecorduid[i]) - strunzone(grecorduid[i]); - grecorduid[i] = strzone(grecorduid[i-1]); - } - } + oldrec = race_readTime(GetMapname(), newpos); + oldrec_holder = race_readName(GetMapname(), newpos); // store new ranking - if (pos == 1) { - db_put(ServerProgsDB, strcat(GetMapname(), rr, "time"), ftos(t)); - db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname"), e.netname); - db_put(ServerProgsDB, strcat(GetMapname(), rr, "crypto_idfp"), e.crypto_idfp); - - grecordtime[0] = t; - - if (grecordholder[0]) - strunzone(grecordholder[0]); - grecordholder[0] = strzone(e.netname); - if (grecorduid[0]) - strunzone(grecorduid[0]); - grecorduid[0] = strzone(e.crypto_idfp); + race_writeTime(GetMapname(), t, myuid); + + if (newpos == 1) { write_recordmarker(e, time - TIME_DECODE(t), TIME_DECODE(t)); race_send_recordtime(MSG_ALL); - } else { - db_put(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(pos-1)), ftos(t)); - db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(pos-1)), e.netname); - db_put(ServerProgsDB, strcat(GetMapname(), rr, "crypto_idfp", ftos(pos-1)), e.crypto_idfp); - - grecordtime[pos-1] = t; - - if (grecordholder[pos-1]) - strunzone(grecordholder[pos-1]); - grecordholder[pos-1] = strzone(e.netname); - if (grecorduid[pos-1]) - strunzone(grecorduid[pos-1]); - grecorduid[pos-1] = strzone(e.crypto_idfp); } - if (pos == RANKINGS_CNT) - worst_time = t; - - race_SendRankings(pos, prevpos, 0, MSG_ALL); + race_SendRankings(newpos, player_prevpos, 0, MSG_ALL); if(rankings_reply) strunzone(rankings_reply); rankings_reply = strzone(getrankings()); - if(pos == 1) { - if(pos == prevpos) { + if(newpos == 1) { + if(newpos == player_prevpos) { recorddifference = strcat(" ^2[-", TIME_ENCODED_TOSTRING(oldrec - t), "]"); - bprint(e.netname, "^1 improved their 1st place record with ", TIME_ENCODED_TOSTRING(t), recorddifference, "\n"); + bprint(mynetname, "^1 improved their 1st place record with ", TIME_ENCODED_TOSTRING(t), recorddifference, "\n"); } else if (oldrec == 0) { - bprint(e.netname, "^1 set the 1st place record with ", TIME_ENCODED_TOSTRING(t), "\n"); + bprint(mynetname, "^1 set the 1st place record with ", TIME_ENCODED_TOSTRING(t), "\n"); } else { recorddifference = strcat(" ^2[-", TIME_ENCODED_TOSTRING(oldrec - t), "]"); - bprint(e.netname, "^1 broke ", grecordholder[pos], "^1's 1st place record with ", strcat(TIME_ENCODED_TOSTRING(t), recorddifference, "\n")); + bprint(mynetname, "^1 broke ", oldrec_holder, "^1's 1st place record with ", strcat(TIME_ENCODED_TOSTRING(t), recorddifference, "\n")); } race_SendStatus(3, e); // "new server record" + Send_KillNotification(e.netname, TIME_ENCODED_TOSTRING(t), "", RACE_SERVER_RECORD, MSG_RACE); } else { - if(pos == prevpos) { + if(newpos == player_prevpos) { recorddifference = strcat(" ^2[-", TIME_ENCODED_TOSTRING(oldrec - t), "]"); - bprint(e.netname, "^5 improved their ", race_PlaceName(pos), " ^5place record with ", TIME_ENCODED_TOSTRING(t), recorddifference, "\n"); + bprint(mynetname, "^5 improved their ", race_placeName(newpos), " ^5place record with ", TIME_ENCODED_TOSTRING(t), recorddifference, "\n"); race_SendStatus(1, e); // "new time" + Send_KillNotification(e.netname, TIME_ENCODED_TOSTRING(t), "", RACE_NEW_TIME, MSG_RACE); } else if (oldrec == 0) { - bprint(e.netname, "^2 set the ", race_PlaceName(pos), " ^2place record with ", TIME_ENCODED_TOSTRING(t), "\n"); + bprint(mynetname, "^2 set the ", race_placeName(newpos), " ^2place record with ", TIME_ENCODED_TOSTRING(t), "\n"); race_SendStatus(2, e); // "new rank" + Send_KillNotification(e.netname, TIME_ENCODED_TOSTRING(t), "", RACE_NEW_RANK, MSG_RACE); } else { recorddifference = strcat(" ^2[-", TIME_ENCODED_TOSTRING(oldrec - t), "]"); - bprint(e.netname, "^2 broke ", grecordholder[pos], "^2's ", race_PlaceName(pos), " ^2place record with ", strcat(TIME_ENCODED_TOSTRING(t), recorddifference, "\n")); + bprint(mynetname, "^2 broke ", oldrec_holder, "^2's ", race_placeName(newpos), " ^2place record with ", strcat(TIME_ENCODED_TOSTRING(t), recorddifference, "\n")); race_SendStatus(2, e); // "new rank" + Send_KillNotification(e.netname, TIME_ENCODED_TOSTRING(t), "", RACE_NEW_TIME, MSG_RACE); } } } -void race_DeleteTime(float pos) { - float i; +void race_deleteTime(string map, float pos) { + string rr; + if(g_cts) + rr = CTS_RECORD; + else + rr = RACE_RECORD; - for (i = pos-1; i <= RANKINGS_CNT-1; ++i) { - if (i == 0) { - db_put(ServerProgsDB, strcat(GetMapname(), rr, "time"), ftos(grecordtime[1])); - db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname"), grecordholder[1]); - db_put(ServerProgsDB, strcat(GetMapname(), rr, "crypto_idfp"), grecorduid[1]); - grecordtime[0] = grecordtime[1]; - if (grecordholder[i]) - strunzone(grecordholder[0]); - grecordholder[0] = strzone(grecordholder[1]); - - if (grecorduid[i]) - strunzone(grecorduid[0]); - grecorduid[0] = strzone(grecorduid[1]); - } - else if (i == RANKINGS_CNT-1) { - db_put(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(i)), string_null); - db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(i)), string_null); - db_put(ServerProgsDB, strcat(GetMapname(), rr, "crypto_idfp", ftos(i)), string_null); - grecordtime[i] = 0; - if (grecordholder[i]) - strunzone(grecordholder[i]); - grecordholder[i] = string_null; - - if (grecorduid[i]) - strunzone(grecorduid[i]); - grecorduid[i] = string_null; + float i; + for (i = pos; i <= RANKINGS_CNT; ++i) { + if (i == RANKINGS_CNT) { + db_put(ServerProgsDB, strcat(map, rr, "time", ftos(i)), string_null); + db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(i)), string_null); } else { - db_put(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(i)), ftos(grecordtime[i+1])); - db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(i)), grecordholder[i+1]); - db_put(ServerProgsDB, strcat(GetMapname(), rr, "crypto_idfp", ftos(i)), grecorduid[i+1]); - grecordtime[i] = grecordtime[i+1]; - if (grecordholder[i]) - strunzone(grecordholder[i]); - grecordholder[i] = strzone(grecordholder[i+1]); - - if (grecorduid[i]) - strunzone(grecorduid[i]); - grecorduid[i] = strzone(grecorduid[i+1]); + db_put(ServerProgsDB, strcat(map, rr, "time", ftos(i)), ftos(race_readTime(GetMapname(), i+1))); + db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(i)), race_readUID(GetMapname(), i+1)); } } @@ -381,8 +239,6 @@ void race_DeleteTime(float pos) { if(rankings_reply) strunzone(rankings_reply); rankings_reply = strzone(getrankings()); - - worst_time = 0; } void race_SendTime(entity e, float cp, float t, float tvalid) @@ -441,8 +297,13 @@ void race_SendTime(entity e, float cp, float t, float tvalid) if(t != 0) { if(cp == race_timed_checkpoint) - race_SetTime(e, t, recordtime); - + { + race_setTime(GetMapname(), t, e.crypto_idfp, e.netname, e); + if(g_cts && cvar("g_cts_finish_kill_delay")) + { + CTS_ClientKill(cvar("g_cts_finish_kill_delay")); + } + } if(t < recordtime || recordtime == 0) { race_checkpoint_records[cp] = t; diff --git a/qcsrc/server/t_quake3.qc b/qcsrc/server/t_quake3.qc index cffe88bd7f..3d3f1d626e 100644 --- a/qcsrc/server/t_quake3.qc +++ b/qcsrc/server/t_quake3.qc @@ -39,12 +39,29 @@ void spawnfunc_item_armor_combat() { spawnfunc_item_armor_big(); } void spawnfunc_item_armor_shard() { spawnfunc_item_armor_small(); } void spawnfunc_item_enviro() { spawnfunc_item_invincible(); } -// weapon remove ent from defrag +// weapon remove ent from df +void target_init_verify() +{ + entity trigger, targ; + for(trigger = world; (trigger = find(trigger, classname, "trigger_multiple")); ) + for(targ = world; (targ = find(targ, targetname, trigger.target)); ) + if (targ.classname == "target_init" || targ.classname == "target_give" || targ.classname == "target_items") + { + targ.wait = -2; + targ.delay = 0; + + setsize(targ, trigger.mins, trigger.maxs); + setorigin(targ, trigger.origin); + //remove(trigger); + } +} + void spawnfunc_target_init() { self.spawnflags = 0; // remove all weapons except the ones listed below self.netname = "laser uzi"; // keep these weapons through the remove trigger spawnfunc_target_items(); + InitializeEntity(self, target_init_verify, INITPRIO_FINDTARGET); } // weapon give ent from defrag @@ -85,6 +102,7 @@ void target_give_init() } self.spawnflags = 2; spawnfunc_target_items(); + InitializeEntity(self, target_init_verify, INITPRIO_FINDTARGET); } void spawnfunc_target_give()