X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Frace.qc;h=5ccb607e926ce13362fc2d11e4c1e444b7bdeb01;hb=f22b9f83b24cae4a7e31ef6e310214be7d735a4d;hp=c5a96b62a266509c42c327f6f862b7bed6c2b8ee;hpb=80ffd95ff0679bd8fdc1902cdb6646e8905bb29a;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/race.qc b/qcsrc/server/race.qc index c5a96b62a..5ccb607e9 100644 --- a/qcsrc/server/race.qc +++ b/qcsrc/server/race.qc @@ -66,11 +66,6 @@ void write_recordmarker(entity pl, float tstart, float dt) IntrusiveList g_race_targets; IntrusiveList g_racecheckpoints; -STATIC_INIT(g_race) -{ - g_race_targets = IL_NEW(); - g_racecheckpoints = IL_NEW(); -} void race_InitSpectator() { @@ -260,7 +255,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 @@ -287,7 +281,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); @@ -298,6 +292,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)) @@ -378,7 +422,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) @@ -421,7 +465,7 @@ void race_deleteTime(string map, float pos) } } - race_SendRankings(pos, 0, 1, MSG_ALL); + race_SendRanking(pos, 0, 1, MSG_ALL); if(pos == 1) race_send_recordtime(MSG_ALL); @@ -795,9 +839,35 @@ bool race_waypointsprite_visible_for_player(entity this, entity player, entity v return false; } +void defrag_waypointsprites(entity targeted, entity checkpoint) +{ + // 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) + + 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) + defrag_waypointsprites(t, checkpoint); + } +} + void trigger_race_checkpoint_verify(entity this) { - static bool have_verified; + static bool have_verified; if (have_verified) return; have_verified = true; @@ -815,7 +885,7 @@ void trigger_race_checkpoint_verify(entity this) 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")); - } + } if (i == 0) { // qualifying only @@ -823,7 +893,7 @@ void trigger_race_checkpoint_verify(entity this) pl_race_place = race_lowest_place_spawn; 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 qualifying) - bailing out")); - } + } // race only (initial spawn) g_race_qualifying = 0; @@ -831,7 +901,7 @@ void trigger_race_checkpoint_verify(entity this) pl_race_place = p; 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 initially spawning in race) - bailing out")); - } + } } } } @@ -842,7 +912,7 @@ void trigger_race_checkpoint_verify(entity this) pl_race_place = race_lowest_place_spawn; if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) { error(strcat("Checkpoint 0 misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for qualifying) - bailing out")); - } + } } else { pl_race_checkpoint = race_NextCheckpoint(0); g_race_qualifying = 1; @@ -864,8 +934,8 @@ void trigger_race_checkpoint_verify(entity this) for (entity cp = NULL; (cp = find(cp, classname, "target_checkpoint"));) { if (argv(0) == cp.targetname) { cp.race_checkpoint = stof(argv(1)); - } - } + } + } } fclose(fh); } @@ -873,37 +943,12 @@ void trigger_race_checkpoint_verify(entity this) g_race_qualifying = qual; - IL_EACH(g_race_targets, it.classname == "target_checkpoint" || it.classname == "target_startTimer" || it.classname == "target_stopTimer", - { - if(it.targetname == "" || !it.targetname) // somehow this is a case... - continue; - entity cpt = it; - FOREACH_ENTITY_STRING(target, cpt.targetname, - { - vector org = (it.absmin + it.absmax) * 0.5; - if(cpt.race_checkpoint == 0) - WaypointSprite_SpawnFixed(WP_RaceStart, org, it, sprite, RADARICON_NONE); - else - WaypointSprite_SpawnFixed(WP_RaceCheckpoint, org, it, sprite, RADARICON_NONE); - - it.sprite.realowner = cpt; - it.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player; - }); - }); - if (race_timed_checkpoint) { if (defrag_ents) { IL_EACH(g_race_targets, it.classname == "target_checkpoint" || it.classname == "target_startTimer" || it.classname == "target_stopTimer", { - entity cpt = it; - if(it.classname == "target_startTimer" || it.classname == "target_stopTimer") { - if(it.targetname == "" || !it.targetname) // somehow this is a case... - continue; - FOREACH_ENTITY_STRING(target, cpt.targetname, { - if(it.sprite) - WaypointSprite_UpdateSprites(it.sprite, ((cpt.classname == "target_startTimer") ? WP_RaceStart : WP_RaceFinish), WP_Null, WP_Null); - }); - } + defrag_waypointsprites(it, it); + if(it.classname == "target_checkpoint") { if(it.race_checkpoint == -2) defragcpexists = -1; // something's wrong with the defrag cp file or it has not been written yet, set defragcpexists to -1 so that it will be rewritten when someone finishes @@ -914,17 +959,17 @@ void trigger_race_checkpoint_verify(entity this) for (entity cp = NULL; (cp = find(cp, classname, "target_checkpoint"));) { if (cp.race_checkpoint > largest_cp_id) { largest_cp_id = cp.race_checkpoint; - } - } + } + } for (entity cp = NULL; (cp = find(cp, classname, "target_stopTimer"));) { cp.race_checkpoint = largest_cp_id + 1; // finish line - } + } race_highest_checkpoint = largest_cp_id + 1; race_timed_checkpoint = largest_cp_id + 1; } else { for (entity cp = NULL; (cp = find(cp, classname, "target_stopTimer"));) { cp.race_checkpoint = 255; // finish line - } + } race_highest_checkpoint = 255; race_timed_checkpoint = 255; } @@ -933,14 +978,14 @@ void trigger_race_checkpoint_verify(entity this) { if (it.race_checkpoint == 0) { WaypointSprite_UpdateSprites(it.sprite, WP_RaceStart, WP_Null, WP_Null); - } else if (it.race_checkpoint == race_timed_checkpoint) { + } else if (it.race_checkpoint == race_timed_checkpoint) { WaypointSprite_UpdateSprites(it.sprite, WP_RaceFinish, WP_Null, WP_Null); } - }); + }); } } - if (defrag_ents) { + if (defrag_ents) { /* The following hack shall be removed when per-player trigger_multiple.wait is implemented for cts */ for (entity trigger = NULL; (trigger = find(trigger, classname, "trigger_multiple")); ) { for (entity targ = NULL; (targ = find(targ, targetname, trigger.target)); ) { if (targ.classname == "target_checkpoint" || targ.classname == "target_startTimer" || targ.classname == "target_stopTimer") { @@ -1042,8 +1087,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); } @@ -1087,8 +1138,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); }