X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Frace.qc;h=f8af3fc5f716c5ca12eb604c6f32ecd55c64d496;hb=e88e1e15090f826fe3ac9b006e89eca0d1ecfe68;hp=f3f0ac907575f7e93e235c4b34e5d0fc6b5420d3;hpb=3e6e644488b54b638078fb88b88c643e103ac8e1;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/race.qc b/qcsrc/server/race.qc index f3f0ac907..f8af3fc5f 100644 --- a/qcsrc/server/race.qc +++ b/qcsrc/server/race.qc @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,8 @@ #include #include +.string stored_netname; // TODO: store this information independently of race-based gamemodes + string uid2name(string myuid) { string s = db_get(ServerProgsDB, strcat("/uid2name/", myuid)); @@ -58,17 +61,12 @@ void write_recordmarker(entity pl, float tstart, float dt) // also write a marker into demo files for demotc-race-record-extractor to find stuffcmd(pl, strcat( - strcat("//", strconv(2, 0, 0, GetGametype()), " RECORD SET ", TIME_ENCODED_TOSTRING(TIME_ENCODE(dt))), + strcat("//", strconv(2, 0, 0, GetGametype()), " RECORD SET ", TIME_ENCODED_TOSTRING(TIME_ENCODE(dt), false)), " ", ftos(tstart), " ", ftos(dt), "\n")); } IntrusiveList g_race_targets; IntrusiveList g_racecheckpoints; -STATIC_INIT(g_race) -{ - g_race_targets = IL_NEW(); - g_racecheckpoints = IL_NEW(); -} void race_InitSpectator() { @@ -79,16 +77,12 @@ void race_InitSpectator() float race_readTime(string map, float pos) { - string rr = ((g_cts) ? CTS_RECORD : ((g_ctf) ? CTF_RECORD : RACE_RECORD)); - - return stof(db_get(ServerProgsDB, strcat(map, rr, "time", ftos(pos)))); + return stof(db_get(ServerProgsDB, strcat(map, record_type, "time", ftos(pos)))); } string race_readUID(string map, float pos) { - string rr = ((g_cts) ? CTS_RECORD : ((g_ctf) ? CTF_RECORD : RACE_RECORD)); - - return db_get(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(pos))); + return db_get(ServerProgsDB, strcat(map, record_type, "crypto_idfp", ftos(pos))); } float race_readPos(string map, float t) @@ -105,8 +99,6 @@ float race_readPos(string map, float t) void race_writeTime(string map, float t, string myuid) { - string rr = ((g_cts) ? CTS_RECORD : ((g_ctf) ? CTF_RECORD : RACE_RECORD)); - float newpos; newpos = race_readPos(map, t); @@ -118,11 +110,11 @@ void race_writeTime(string map, float t, string myuid) } if (prevpos) { - // player improved his existing record, only have to iterate on ranks between new and old recs + // player improved their 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)); + db_put(ServerProgsDB, strcat(map, record_type, "time", ftos(i)), ftos(race_readTime(map, i - 1))); + db_put(ServerProgsDB, strcat(map, record_type, "crypto_idfp", ftos(i)), race_readUID(map, i - 1)); } } else @@ -132,22 +124,34 @@ void race_writeTime(string map, float t, string myuid) { float other_time = race_readTime(map, i - 1); if (other_time) { - db_put(ServerProgsDB, strcat(map, rr, "time", ftos(i)), ftos(other_time)); - db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(i)), race_readUID(map, i - 1)); + db_put(ServerProgsDB, strcat(map, record_type, "time", ftos(i)), ftos(other_time)); + db_put(ServerProgsDB, strcat(map, record_type, "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); + db_put(ServerProgsDB, strcat(map, record_type, "time", ftos(newpos)), ftos(t)); + db_put(ServerProgsDB, strcat(map, record_type, "crypto_idfp", ftos(newpos)), myuid); } string race_readName(string map, float pos) { - string rr = ((g_cts) ? CTS_RECORD : ((g_ctf) ? CTF_RECORD : RACE_RECORD)); + return uid2name(db_get(ServerProgsDB, strcat(map, record_type, "crypto_idfp", ftos(pos)))); +} - return uid2name(db_get(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(pos)))); +void race_checkAndWriteName(entity player) +{ + if(CS_CVAR(player).cvar_cl_allow_uidtracking == 1 && CS_CVAR(player).cvar_cl_allow_uid2name == 1) + { + if (!player.stored_netname) + player.stored_netname = strzone(uid2name(player.crypto_idfp)); + if(player.stored_netname != player.netname) + { + db_put(ServerProgsDB, strcat("/uid2name/", player.crypto_idfp), player.netname); + strcpy(player.stored_netname, player.netname); + } + } } @@ -252,7 +256,6 @@ void race_send_recordtime(float msg) WriteInt24_t(msg, race_readTime(GetMapname(), 1)); } - void race_send_speedaward(float msg) { // send the best speed of the round @@ -279,7 +282,7 @@ void race_send_rankings_cnt(float msg) WriteByte(msg, m); } -void race_SendRankings(float pos, float prevpos, float del, float msg) +void race_SendRanking(float pos, float prevpos, float del, float msg) { WriteHeader(msg, TE_CSQC_RACE); WriteByte(msg, RACE_NET_SERVER_RANKINGS); @@ -290,6 +293,56 @@ void race_SendRankings(float pos, float prevpos, float del, float msg) WriteInt24_t(msg, race_readTime(GetMapname(), pos)); } +void race_SpeedAwardFrame(entity player) +{ + if (IS_OBSERVER(player)) + return; + + if(vdist(player.velocity - player.velocity_z * '0 0 1', >, speedaward_speed)) + { + speedaward_speed = vlen(player.velocity - player.velocity_z * '0 0 1'); + speedaward_holder = player.netname; + speedaward_uid = player.crypto_idfp; + speedaward_lastupdate = time; + } + if (speedaward_speed > speedaward_lastsent && (time - speedaward_lastupdate > 1 || intermission_running)) + { + race_send_speedaward(MSG_ALL); + speedaward_lastsent = speedaward_speed; + if (speedaward_speed > speedaward_alltimebest && speedaward_uid != "") + { + speedaward_alltimebest = speedaward_speed; + speedaward_alltimebest_holder = speedaward_holder; + speedaward_alltimebest_uid = speedaward_uid; + db_put(ServerProgsDB, strcat(GetMapname(), record_type, "speed/speed"), ftos(speedaward_alltimebest)); + db_put(ServerProgsDB, strcat(GetMapname(), record_type, "speed/crypto_idfp"), speedaward_alltimebest_uid); + race_send_speedaward_alltimebest(MSG_ALL); + } + } +} + +void race_SendAll(entity player, bool only_rankings) +{ + if(!IS_REAL_CLIENT(player)) + return; + + msg_entity = player; + if (!only_rankings) + { + race_send_recordtime(MSG_ONE); + race_send_speedaward(MSG_ONE); + + speedaward_alltimebest = stof(db_get(ServerProgsDB, strcat(GetMapname(), record_type, "speed/speed"))); + speedaward_alltimebest_holder = uid2name(db_get(ServerProgsDB, strcat(GetMapname(), record_type, "speed/crypto_idfp"))); + race_send_speedaward_alltimebest(MSG_ONE); + } + + int m = min(RANKINGS_CNT, autocvar_g_cts_send_rankings_cnt); + race_send_rankings_cnt(MSG_ONE); + for (int i = 1; i <= m; ++i) + race_SendRanking(i, 0, 0, MSG_ONE); +} + void race_SendStatus(float id, entity e) { if(!IS_REAL_CLIENT(e)) @@ -370,7 +423,7 @@ void race_setTime(string map, float t, string myuid, string mynetname, entity e, race_send_recordtime(MSG_ALL); } - race_SendRankings(newpos, player_prevpos, 0, MSG_ALL); + race_SendRanking(newpos, player_prevpos, 0, MSG_ALL); strcpy(rankings_reply, getrankings()); if(newpos == player_prevpos) @@ -398,24 +451,22 @@ void race_setTime(string map, float t, string myuid, string mynetname, entity e, void race_deleteTime(string map, float pos) { - string rr = ((g_cts) ? CTS_RECORD : ((g_ctf) ? CTF_RECORD : RACE_RECORD)); - for(int i = pos; i <= RANKINGS_CNT; ++i) { string therank = ftos(i); if (i == RANKINGS_CNT) { - db_remove(ServerProgsDB, strcat(map, rr, "time", therank)); - db_remove(ServerProgsDB, strcat(map, rr, "crypto_idfp", therank)); + db_remove(ServerProgsDB, strcat(map, record_type, "time", therank)); + db_remove(ServerProgsDB, strcat(map, record_type, "crypto_idfp", therank)); } else { - db_put(ServerProgsDB, strcat(map, rr, "time", therank), ftos(race_readTime(GetMapname(), i+1))); - db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", therank), race_readUID(GetMapname(), i+1)); + db_put(ServerProgsDB, strcat(map, record_type, "time", therank), ftos(race_readTime(GetMapname(), i+1))); + db_put(ServerProgsDB, strcat(map, record_type, "crypto_idfp", therank), race_readUID(GetMapname(), i+1)); } } - race_SendRankings(pos, 0, 1, MSG_ALL); + race_SendRanking(pos, 0, 1, MSG_ALL); if(pos == 1) race_send_recordtime(MSG_ALL); @@ -424,8 +475,6 @@ void race_deleteTime(string map, float pos) void race_SendTime(entity e, float cp, float t, float tvalid) { - float snew, l; - if(g_race_qualifying) t += e.race_penalty_accumulator; @@ -435,23 +484,15 @@ void race_SendTime(entity e, float cp, float t, float tvalid) if(cp == race_timed_checkpoint) // finish line if (!CS(e).race_completed) { - float s; - if(g_race_qualifying) + int s = GameRules_scoring_add(e, RACE_FASTEST, 0); + if(!s || t < s) + GameRules_scoring_add(e, RACE_FASTEST, t - s); + if(!g_race_qualifying) { - s = GameRules_scoring_add(e, RACE_FASTEST, 0); - if(!s || t < s) - GameRules_scoring_add(e, RACE_FASTEST, t - s); - } - else - { - s = GameRules_scoring_add(e, RACE_FASTEST, 0); - if(!s || t < s) - GameRules_scoring_add(e, RACE_FASTEST, t - s); - s = GameRules_scoring_add(e, RACE_TIME, 0); - snew = TIME_ENCODE(time - game_starttime); + int snew = TIME_ENCODE(time - game_starttime); GameRules_scoring_add(e, RACE_TIME, snew - s); - l = GameRules_scoring_add_team(e, RACE_LAPS, 1); + int l = GameRules_scoring_add_team(e, RACE_LAPS, 1); if(autocvar_fraglimit) if(l >= autocvar_fraglimit) @@ -461,6 +502,9 @@ void race_SendTime(entity e, float cp, float t, float tvalid) { CS(e).race_completed = 1; MAKE_INDEPENDENT_PLAYER(e); + if(e.bot_attack) + IL_REMOVE(g_bot_targets, e); + e.bot_attack = false; Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_FINISHED, e.netname); ClientData_Touch(e); } @@ -791,26 +835,26 @@ bool race_waypointsprite_visible_for_player(entity this, entity player, entity v void defrag_waypointsprites(entity targeted, entity checkpoint) { - for(entity t = findchain(target, targeted.targetname); t; t = t.chain) - { - if(t.modelindex) - { - entity s = WP_RaceStart; + // bones_was_here: spawn a waypoint for every entity with a bmodel + // that directly or indirectly targets this checkpoint + // (anything a player could touch or shoot to activate this cp) - if(checkpoint.classname == "target_checkpoint") - s = WP_RaceCheckpoint; - else if(checkpoint.classname == "target_stopTimer") - s = WP_RaceFinish; - - vector o = (t.absmin + t.absmax) * 0.5; - - WaypointSprite_SpawnFixed(s, o, t, sprite, RADARICON_NONE); + entity s = WP_RaceCheckpoint; + if (checkpoint.classname == "target_startTimer") + s = WP_RaceStart; + else if (checkpoint.classname == "target_stopTimer") + s = WP_RaceFinish; + for (entity t = findchain(target, targeted.targetname); t; t = t.chain) + { + if (t.modelindex) + { + WaypointSprite_SpawnFixed(s, (t.absmin + t.absmax) * 0.5, t, sprite, RADARICON_NONE); t.sprite.realowner = checkpoint; t.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player; } - if(t.targetname) + if (t.targetname) defrag_waypointsprites(t, checkpoint); } } @@ -821,7 +865,7 @@ void trigger_race_checkpoint_verify(entity this) if (have_verified) return; have_verified = true; - bool qual = g_race_qualifying; + int qual = g_race_qualifying; int pl_race_checkpoint = 0; int pl_race_place = 0; @@ -831,7 +875,7 @@ void trigger_race_checkpoint_verify(entity this) pl_race_checkpoint = race_NextCheckpoint(i); // race only (middle of the race) - g_race_qualifying = false; + g_race_qualifying = 0; pl_race_place = 0; if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) { error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for respawning in race) - bailing out")); @@ -984,7 +1028,7 @@ vector trigger_race_checkpoint_spawn_evalfunc(entity this, entity player, entity if(pl > race_highest_place_spawn) pl = 0; if(pl == 0 && !player.race_started) - pl = race_highest_place_spawn; // use last place if he has not even touched finish yet + pl = race_highest_place_spawn; // use last place if they have not even touched finish yet if(spot.race_place != pl) return '-1 0 0'; } @@ -1037,8 +1081,14 @@ spawnfunc(trigger_race_checkpoint) this.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player; this.spawn_evalfunc = trigger_race_checkpoint_spawn_evalfunc; + if (!g_racecheckpoints) + g_racecheckpoints = IL_NEW(); IL_PUSH(g_racecheckpoints, this); + // trigger_race_checkpoint_verify checks this list too + if (!g_race_targets) + g_race_targets = IL_NEW(); + InitializeEntity(this, trigger_race_checkpoint_verify, INITPRIO_FINDTARGET); } @@ -1082,8 +1132,14 @@ void target_checkpoint_setup(entity this) race_timed_checkpoint = 1; + if (!g_race_targets) + g_race_targets = IL_NEW(); IL_PUSH(g_race_targets, this); + // trigger_race_checkpoint_verify checks this list too + if (!g_racecheckpoints) + g_racecheckpoints = IL_NEW(); + InitializeEntity(this, trigger_race_checkpoint_verify, INITPRIO_FINDTARGET); }