X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Frace.qc;h=fbf1eaa185af29a2b6a5d3ab61b72410e6763e6c;hb=61704462bb3c8ce7bfa7f815dcd62e6ff3189c82;hp=8cc7d322c4e3a3fedb09346a9f9fe559fb67d137;hpb=a59c12d71fa599891fc1d658aeea2f546d89d9e4;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/race.qc b/qcsrc/server/race.qc index 8cc7d322c..fbf1eaa18 100644 --- a/qcsrc/server/race.qc +++ b/qcsrc/server/race.qc @@ -1,3 +1,20 @@ +#include "race.qh" +#include "_all.qh" + +#include "cl_client.qh" +#include "portals.qh" +#include "scores.qh" +#include "spawnpoints.qh" +#include "bot/waypoints.qh" +#include "bot/navigation.qh" +#include "command/getreplies.qh" +#include "../common/deathtypes.qh" +#include "../common/notifications.qh" +#include "../common/mapinfo.qh" +#include "../warpzonelib/util_server.qh" + +void W_Porto_Fail(float failhard); + float race_readTime(string map, float pos) { string rr = (g_cts) ? CTS_RECORD : RACE_RECORD; @@ -67,15 +84,14 @@ string race_readName(string map, float pos) } -#define MAX_CHECKPOINTS 255 +const float MAX_CHECKPOINTS = 255; -void spawnfunc_target_checkpoint(); +spawnfunc(target_checkpoint); .float race_penalty; .float race_penalty_accumulator; .string race_penalty_reason; .float race_checkpoint; // player: next checkpoint that has to be reached -.float race_laptime; .entity race_lastpenalty; .entity sprite; @@ -172,6 +188,27 @@ 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 + WriteByte(msg, SVC_TEMPENTITY); + WriteByte(msg, TE_CSQC_RACE); + WriteByte(msg, RACE_NET_SPEED_AWARD); + WriteInt24_t(msg, floor(speedaward_speed+0.5)); + WriteString(msg, speedaward_holder); +} + +void race_send_speedaward_alltimebest(float msg) +{ + // send the best speed + WriteByte(msg, SVC_TEMPENTITY); + WriteByte(msg, TE_CSQC_RACE); + WriteByte(msg, RACE_NET_SPEED_AWARD_BEST); + WriteInt24_t(msg, floor(speedaward_alltimebest+0.5)); + WriteString(msg, speedaward_alltimebest_holder); +} + void race_SendRankings(float pos, float prevpos, float del, float msg) { WriteByte(msg, SVC_TEMPENTITY); @@ -511,28 +548,28 @@ void dumpsurface(entity e) { float n, si, ni; vector norm, vec; - print("Surfaces of ", etos(e), ":\n"); + LOG_INFO("Surfaces of ", etos(e), ":\n"); - print("TEST = ", ftos(getsurfacenearpoint(e, '0 0 0')), "\n"); + LOG_INFO("TEST = ", ftos(getsurfacenearpoint(e, '0 0 0')), "\n"); for(si = 0; ; ++si) { n = getsurfacenumpoints(e, si); if(n <= 0) break; - print(" Surface ", ftos(si), ":\n"); + LOG_INFO(" Surface ", ftos(si), ":\n"); norm = getsurfacenormal(e, si); - print(" Normal = ", vtos(norm), "\n"); + LOG_INFO(" Normal = ", vtos(norm), "\n"); for(ni = 0; ni < n; ++ni) { vec = getsurfacepoint(e, si, ni); - print(" Point ", ftos(ni), " = ", vtos(vec), " (", ftos(norm * vec), ")\n"); + LOG_INFO(" Point ", ftos(ni), " = ", vtos(vec), " (", ftos(norm * vec), ")\n"); } } } void checkpoint_passed() -{ +{SELFPARAM(); string oldmsg; entity cp; @@ -540,7 +577,7 @@ void checkpoint_passed() { // do not allow portalling through checkpoints trace_plane_normal = normalize(-1 * other.velocity); - self = other; + setself(other); W_Porto_Fail(0); return; } @@ -687,19 +724,19 @@ void checkpoint_use() } float race_waypointsprite_visible_for_player(entity e) -{ +{SELFPARAM(); if(e.race_checkpoint == -1 || self.owner.race_checkpoint == -2) - return TRUE; + return true; else if(e.race_checkpoint == self.owner.race_checkpoint) - return TRUE; + return true; else - return FALSE; + return false; } float have_verified; void trigger_race_checkpoint_verify() -{ - entity oldself, cp; +{SELFPARAM(); + entity cp; float i, p; float qual; @@ -709,8 +746,7 @@ void trigger_race_checkpoint_verify() qual = g_race_qualifying; - oldself = self; - self = spawn(); + setself(spawn()); self.classname = "player"; if(g_race) @@ -722,7 +758,7 @@ void trigger_race_checkpoint_verify() // race only (middle of the race) g_race_qualifying = 0; self.race_place = 0; - if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, FALSE)) + if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, false)) error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(self.race_place), " (used for respawning in race) - bailing out")); if(i == 0) @@ -730,7 +766,7 @@ void trigger_race_checkpoint_verify() // qualifying only g_race_qualifying = 1; self.race_place = race_lowest_place_spawn; - if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, FALSE)) + if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, false)) error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(self.race_place), " (used for qualifying) - bailing out")); // race only (initial spawn) @@ -738,7 +774,7 @@ void trigger_race_checkpoint_verify() for(p = 1; p <= race_highest_place_spawn; ++p) { self.race_place = p; - if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, FALSE)) + if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, false)) error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(self.race_place), " (used for initially spawning in race) - bailing out")); } } @@ -750,7 +786,7 @@ void trigger_race_checkpoint_verify() self.race_checkpoint = race_NextCheckpoint(0); g_race_qualifying = 1; self.race_place = race_lowest_place_spawn; - if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, FALSE)) + if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, false)) error(strcat("Checkpoint 0 misses a spawnpoint with race_place==", ftos(self.race_place), " (used for qualifying) - bailing out")); } else @@ -790,9 +826,9 @@ void trigger_race_checkpoint_verify() if(defrag_ents) { for(cp = world; (cp = find(cp, classname, "target_startTimer"));) - WaypointSprite_UpdateSprites(cp.sprite, "race-start", "", ""); + WaypointSprite_UpdateSprites(cp.sprite, WP_RaceStart, WP_Null, WP_Null); for(cp = world; (cp = find(cp, classname, "target_stopTimer"));) - WaypointSprite_UpdateSprites(cp.sprite, "race-finish", "", ""); + WaypointSprite_UpdateSprites(cp.sprite, WP_RaceFinish, WP_Null, WP_Null); for(cp = world; (cp = find(cp, classname, "target_checkpoint"));) { @@ -825,9 +861,9 @@ void trigger_race_checkpoint_verify() if(cp.sprite) { if(cp.race_checkpoint == 0) - WaypointSprite_UpdateSprites(cp.sprite, "race-start", "", ""); + WaypointSprite_UpdateSprites(cp.sprite, WP_RaceStart, WP_Null, WP_Null); else if(cp.race_checkpoint == race_timed_checkpoint) - WaypointSprite_UpdateSprites(cp.sprite, "race-finish", "", ""); + WaypointSprite_UpdateSprites(cp.sprite, WP_RaceFinish, WP_Null, WP_Null); } } } @@ -858,11 +894,11 @@ void trigger_race_checkpoint_verify() } } remove(self); - self = oldself; + setself(this); } vector trigger_race_checkpoint_spawn_evalfunc(entity player, entity spot, vector current) -{ +{SELFPARAM(); if(g_race_qualifying) { // spawn at first @@ -877,7 +913,7 @@ vector trigger_race_checkpoint_spawn_evalfunc(entity player, entity spot, vector return '-1 0 0'; // try reusing the previous spawn if(self == player.race_respawn_spotref || spot == player.race_respawn_spotref) - current_x += SPAWN_PRIO_RACE_PREVIOUS_SPAWN; + current.x += SPAWN_PRIO_RACE_PREVIOUS_SPAWN; if(self.race_checkpoint == 0) { float pl; @@ -893,7 +929,7 @@ vector trigger_race_checkpoint_spawn_evalfunc(entity player, entity spot, vector return current; } -void spawnfunc_trigger_race_checkpoint() +spawnfunc(trigger_race_checkpoint) { vector o; if(!g_race && !g_cts) { remove(self); return; } @@ -905,7 +941,7 @@ void spawnfunc_trigger_race_checkpoint() self.touch = checkpoint_touch; o = (self.absmin + self.absmax) * 0.5; - tracebox(o, PL_MIN, PL_MAX, o - '0 0 1' * (o_z - self.absmin_z), MOVE_NORMAL, self); + tracebox(o, PL_MIN, PL_MAX, o - '0 0 1' * (o.z - self.absmin.z), MOVE_NORMAL, self); waypoint_spawnforitem_force(self, trace_endpos); self.nearestwaypointtimeout = time + 1000000000; @@ -930,9 +966,9 @@ void spawnfunc_trigger_race_checkpoint() if(!self.race_penalty) { if(self.race_checkpoint) - WaypointSprite_SpawnFixed("race-checkpoint", o, self, sprite, RADARICON_NONE, '1 0.5 0'); + WaypointSprite_SpawnFixed(WP_RaceCheckpoint, o, self, sprite, RADARICON_NONE); else - WaypointSprite_SpawnFixed("race-start-finish", o, self, sprite, RADARICON_NONE, '1 0.5 0'); + WaypointSprite_SpawnFixed(WP_RaceStartFinish, o, self, sprite, RADARICON_NONE); } self.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player; @@ -941,7 +977,7 @@ void spawnfunc_trigger_race_checkpoint() InitializeEntity(self, trigger_race_checkpoint_verify, INITPRIO_FINDTARGET); } -void spawnfunc_target_checkpoint() // defrag entity +spawnfunc(target_checkpoint) // defrag entity { vector o; if(!g_race && !g_cts) { remove(self); return; } @@ -954,7 +990,7 @@ void spawnfunc_target_checkpoint() // defrag entity self.touch = checkpoint_touch; o = (self.absmin + self.absmax) * 0.5; - tracebox(o, PL_MIN, PL_MAX, o - '0 0 1' * (o_z - self.absmin_z), MOVE_NORMAL, self); + tracebox(o, PL_MIN, PL_MAX, o - '0 0 1' * (o.z - self.absmin.z), MOVE_NORMAL, self); waypoint_spawnforitem_force(self, trace_endpos); self.nearestwaypointtimeout = time + 1000000000; @@ -973,17 +1009,17 @@ void spawnfunc_target_checkpoint() // defrag entity race_timed_checkpoint = 1; if(self.race_checkpoint == 0) - WaypointSprite_SpawnFixed("race-start", o, self, sprite, RADARICON_NONE, '1 0.5 0'); + WaypointSprite_SpawnFixed(WP_RaceStart, o, self, sprite, RADARICON_NONE); else - WaypointSprite_SpawnFixed("race-checkpoint", o, self, sprite, RADARICON_NONE, '1 0.5 0'); + WaypointSprite_SpawnFixed(WP_RaceCheckpoint, o, self, sprite, RADARICON_NONE); self.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player; InitializeEntity(self, trigger_race_checkpoint_verify, INITPRIO_FINDTARGET); } -void spawnfunc_target_startTimer() { spawnfunc_target_checkpoint(); } -void spawnfunc_target_stopTimer() { spawnfunc_target_checkpoint(); } +spawnfunc(target_startTimer) { spawnfunc_target_checkpoint(this); } +spawnfunc(target_stopTimer) { spawnfunc_target_checkpoint(this); } void race_AbandonRaceCheck(entity p) { @@ -1006,7 +1042,7 @@ void race_StartCompleting() } void race_PreparePlayer() -{ +{SELFPARAM(); race_ClearTime(self); self.race_place = 0; self.race_started = 0; @@ -1015,7 +1051,7 @@ void race_PreparePlayer() } void race_RetractPlayer() -{ +{SELFPARAM(); if(!g_race && !g_cts) return; if(self.race_respawn_checkpoint == 0 || self.race_respawn_checkpoint == race_timed_checkpoint) @@ -1023,11 +1059,11 @@ void race_RetractPlayer() self.race_checkpoint = self.race_respawn_checkpoint; } -void spawnfunc_info_player_race (void) +spawnfunc(info_player_race) { if(!g_race && !g_cts) { remove(self); return; } ++race_spawns; - spawnfunc_info_player_deathmatch(); + spawnfunc_info_player_deathmatch(this); if(self.race_place > race_highest_place_spawn) race_highest_place_spawn = self.race_place; @@ -1036,9 +1072,8 @@ void spawnfunc_info_player_race (void) } void race_ClearRecords() -{ +{SELFPARAM(); float i; - entity e; for(i = 0; i < MAX_CHECKPOINTS; ++i) { @@ -1048,15 +1083,13 @@ void race_ClearRecords() race_checkpoint_recordholders[i] = string_null; } - e = self; - FOR_EACH_CLIENT(self) + entity e; + FOR_EACH_CLIENT(e) { - float p; - p = self.race_place; - race_PreparePlayer(); - self.race_place = p; + float p = e.race_place; + WITH(entity, self, e, race_PreparePlayer()); + e.race_place = p; } - self = e; } void race_ImposePenaltyTime(entity pl, float penalty, string reason) @@ -1094,7 +1127,7 @@ void race_ImposePenaltyTime(entity pl, float penalty, string reason) } void penalty_touch() -{ +{SELFPARAM(); EXACTTRIGGER_TOUCH; if(other.race_lastpenalty != self) { @@ -1104,11 +1137,11 @@ void penalty_touch() } void penalty_use() -{ +{SELFPARAM(); race_ImposePenaltyTime(activator, self.race_penalty, self.race_penalty_reason); } -void spawnfunc_trigger_race_penalty() +spawnfunc(trigger_race_penalty) { EXACTTRIGGER_INIT; @@ -1178,7 +1211,7 @@ float race_GetFractionalLapCount(entity e) // race_timed_checkpoint == 0: then nextcp==0 means 0.9999x float c, nc; nc = race_highest_checkpoint + 1; - c = (mod(nextcpindex - race_timed_checkpoint + nc + nc - 1, nc) + 1) - bestfraction; + c = ((nextcpindex - race_timed_checkpoint + nc + nc - 1) % nc) + 1 - bestfraction; return l + c / nc; }