From 9efd8541d8cc9c1df4f5a2766a0b6ed7d859ae92 Mon Sep 17 00:00:00 2001 From: div0 Date: Sun, 10 Aug 2008 11:53:53 +0000 Subject: [PATCH] finish g_race_qualifying 2 mode (by adding a race display to csqc) git-svn-id: svn://svn.icculus.org/nexuiz/trunk@4088 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/qcsrc/client/Defs.qc | 13 ++ data/qcsrc/client/Main.qc | 24 +++- data/qcsrc/client/sbar.qc | 61 +++++++-- data/qcsrc/common/constants.qh | 6 +- data/qcsrc/server/race.qc | 203 +++++++++++++++++++++--------- data/qcsrc/server/scores_rules.qc | 5 +- 6 files changed, 232 insertions(+), 80 deletions(-) diff --git a/data/qcsrc/client/Defs.qc b/data/qcsrc/client/Defs.qc index f51ec064e..c6b95e766 100644 --- a/data/qcsrc/client/Defs.qc +++ b/data/qcsrc/client/Defs.qc @@ -175,6 +175,7 @@ float caps_team1, caps_team2; float configdb; string shortmapname; +// QUALIFYING float race_checkpoint; float race_time; float race_laptime; @@ -185,3 +186,15 @@ string race_previousbestname; float race_nextcheckpoint; float race_nextbesttime; string race_nextbestname; + +// RACE +float race_mycheckpoint; +float race_mycheckpointtime; +float race_mycheckpointdelta; +float race_mycheckpointlapsdelta; +string race_mycheckpointenemy; +float race_othercheckpoint; +float race_othercheckpointtime; +float race_othercheckpointdelta; +float race_othercheckpointlapsdelta; +string race_othercheckpointenemy; diff --git a/data/qcsrc/client/Main.qc b/data/qcsrc/client/Main.qc index 09bb508bf..a25aac489 100644 --- a/data/qcsrc/client/Main.qc +++ b/data/qcsrc/client/Main.qc @@ -575,7 +575,7 @@ void Net_ReadRace() switch(b) { - case RACE_NET_CHECKPOINT_HIT: + case RACE_NET_CHECKPOINT_HIT_QUALIFYING: race_checkpoint = ReadByte(); race_time = ReadShort(); race_previousbesttime = ReadShort(); @@ -595,7 +595,7 @@ void Net_ReadRace() race_checkpointtime = 0; break; - case RACE_NET_CHECKPOINT_NEXT: + case RACE_NET_CHECKPOINT_NEXT_QUALIFYING: race_nextcheckpoint = ReadByte(); race_nextbesttime = ReadShort(); @@ -603,6 +603,26 @@ void Net_ReadRace() strunzone(race_nextbestname); race_nextbestname = strzone(ReadString()); break; + + case RACE_NET_CHECKPOINT_HIT_RACE: + race_mycheckpoint = ReadByte(); + race_mycheckpointtime = time; + race_mycheckpointdelta = ReadShort(); + race_mycheckpointlapsdelta = ReadByte(); + if(race_mycheckpointenemy) + strunzone(race_mycheckpointenemy); + race_mycheckpointenemy = strzone(ReadString()); + break; + + case RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT: + race_othercheckpoint = ReadByte(); + race_othercheckpointtime = time; + race_othercheckpointdelta = ReadShort(); + race_othercheckpointlapsdelta = ReadByte(); + if(race_othercheckpointenemy) + strunzone(race_othercheckpointenemy); + race_othercheckpointenemy = strzone(ReadString()); + break; } } diff --git a/data/qcsrc/client/sbar.qc b/data/qcsrc/client/sbar.qc index fd0636e1e..d8b89e79c 100644 --- a/data/qcsrc/client/sbar.qc +++ b/data/qcsrc/client/sbar.qc @@ -934,24 +934,42 @@ void Sbar_DrawScoreboard() sbar = sbar_save; } -string MakeRaceString(float cp, float mytime, float histime, string hisname) +string MakeRaceString(float cp, float mytime, float histime, float lapdelta, string hisname) { string col; string timestr; string cpname; + string lapstr; + lapstr = ""; if(histime == 0) // goal hit { - if(mytime >= 0) + if(mytime > 0) { timestr = strcat("+", ftos_decimals(+mytime, 1)); col = "^1"; } + else if(mytime == 0) + { + timestr = "+0.0"; + col = "^3"; + } else { timestr = strcat("-", ftos_decimals(-mytime, 1)); col = "^2"; } + + if(lapdelta > 0) + { + lapstr = strcat(" (-", ftos(lapdelta), "L)"); + col = "^2"; + } + else if(lapdelta < 0) + { + lapstr = strcat(" (+", ftos(-lapdelta), "L)"); + col = "^1"; + } } else if(histime > 0) // anticipation { @@ -974,7 +992,7 @@ string MakeRaceString(float cp, float mytime, float histime, string hisname) else if(hisname == "") return strcat(col, cpname, " (", timestr, ")"); else - return strcat(col, cpname, " (", timestr, " ", hisname, col, ")"); + return strcat(col, cpname, " (", timestr, " ", strcat(hisname, lapstr), col, ")"); } void dummyfunction(float a1, float a2, float a3, float a4, float a5, float a6, float a7, float a8) @@ -1086,23 +1104,23 @@ void Sbar_Score(float margin) if(gametype == GAME_RACE) { drawfont = sbar_bigfont; + float a; + vector m; + string s; + + m = '0.5 0 0' * vid_conwidth + '0 0.25 0' * vid_conheight; if(race_checkpointtime) { - float a; - vector m; - string s; - - m = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight; a = bound(0, 2 - (time - race_checkpointtime), 1); s = ""; if(a > 0) // just hit a checkpoint? { if(race_time && race_previousbesttime) - s = MakeRaceString(race_checkpoint, race_time / 10 - race_previousbesttime / 10, 0, race_previousbestname); + s = MakeRaceString(race_checkpoint, race_time / 10 - race_previousbesttime / 10, 0, 0, race_previousbestname); else - s = MakeRaceString(race_checkpoint, 0, -1, race_previousbestname); + s = MakeRaceString(race_checkpoint, 0, -1, 0, race_previousbestname); } else { @@ -1111,7 +1129,7 @@ void Sbar_Score(float margin) a = bound(0, 2 - ((race_laptime + race_nextbesttime/10) - time), 1); if(a > 0) // next one? { - s = MakeRaceString(race_nextcheckpoint, time - race_laptime, race_nextbesttime / 10, race_nextbestname); + s = MakeRaceString(race_nextcheckpoint, time - race_laptime, race_nextbesttime / 10, 0, race_nextbestname); } } } @@ -1120,13 +1138,30 @@ void Sbar_Score(float margin) if(a > 0) { dummyfunction(0, 0, 0, 0, 0, 0, 0, 0); // work around DP bug (set OFS_PARAM5 to 0) - drawcolorcodedstring(m - '0 80 0' - '8 0 0' * stringwidth(s, TRUE), s, '16 16 0', sbar_alpha_fg * a, 0); + drawcolorcodedstring(m - '0 16 0' - '8 0 0' * stringwidth(s, TRUE), s, '16 16 0', sbar_alpha_fg * a, 0); } if(race_laptime) { s = mmsss(10*(time - race_laptime)); - drawstring(m - '0 64 0' - '16 0 0' * stringwidth(s, FALSE), s, '32 32 0', '1 1 1', sbar_alpha_fg, 0); + drawstring(m - '0 0 0' - '16 0 0' * stringwidth(s, FALSE), s, '32 32 0', '1 1 1', sbar_alpha_fg, 0); + } + } + else + { + if(race_mycheckpointtime) + { + a = bound(0, 2 - (time - race_mycheckpointtime), 1); + s = MakeRaceString(race_mycheckpoint, race_mycheckpointdelta / 10, -!race_mycheckpointenemy, race_mycheckpointlapsdelta, race_mycheckpointenemy); + dummyfunction(0, 0, 0, 0, 0, 0, 0, 0); // work around DP bug (set OFS_PARAM5 to 0) + drawcolorcodedstring(m - '0 16 0' - '8 0 0' * stringwidth(s, TRUE), s, '16 16 0', sbar_alpha_fg * a, 0); + } + if(race_othercheckpointtime && race_othercheckpointenemy != "") + { + a = bound(0, 2 - (time - race_othercheckpointtime), 1); + s = MakeRaceString(race_othercheckpoint, -race_othercheckpointdelta / 10, -!race_othercheckpointenemy, race_othercheckpointlapsdelta, race_othercheckpointenemy); + dummyfunction(0, 0, 0, 0, 0, 0, 0, 0); // work around DP bug (set OFS_PARAM5 to 0) + drawcolorcodedstring(m - '0 0 0' - '8 0 0' * stringwidth(s, TRUE), s, '16 16 0', sbar_alpha_fg * a, 0); } } diff --git a/data/qcsrc/common/constants.qh b/data/qcsrc/common/constants.qh index 1fa0529e7..ac6c4715f 100644 --- a/data/qcsrc/common/constants.qh +++ b/data/qcsrc/common/constants.qh @@ -202,9 +202,11 @@ const float MAPVOTE_NET_UPDATE = 1; const float MAPVOTE_NET_PIC = 2; const float MAPVOTE_NET_OWNVOTE = 3; -const float RACE_NET_CHECKPOINT_HIT = 0; // byte checkpoint, short time, short recordtime, string recordholder +const float RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder const float RACE_NET_CHECKPOINT_CLEAR = 1; -const float RACE_NET_CHECKPOINT_NEXT = 2; // byte nextcheckpoint, short recordtime, string recordholder +const float RACE_NET_CHECKPOINT_NEXT_QUALIFYING = 2; // byte nextcheckpoint, short recordtime, string recordholder +const float RACE_NET_CHECKPOINT_HIT_RACE = 3; // byte checkpoint, short delta, byte lapsdelta, string opponent +const float RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT = 4; // byte checkpoint, short delta, byte lapsdelta, string opponent /** * Lower scores are better (e.g. suicides) diff --git a/data/qcsrc/server/race.qc b/data/qcsrc/server/race.qc index 40a5adc6c..757fe9f63 100644 --- a/data/qcsrc/server/race.qc +++ b/data/qcsrc/server/race.qc @@ -7,6 +7,9 @@ float race_checkpoint_records[MAX_CHECKPOINTS]; string race_checkpoint_recordholders[MAX_CHECKPOINTS]; +float race_checkpoint_lasttimes[MAX_CHECKPOINTS]; +float race_checkpoint_lastlaps[MAX_CHECKPOINTS]; +entity race_checkpoint_lastplayers[MAX_CHECKPOINTS]; float race_highest_checkpoint; float race_highest_place_spawn; @@ -54,7 +57,7 @@ void race_SendNextCheckpoint(entity e) msg_entity = e; WriteByte(MSG_ONE, SVC_TEMPENTITY); WriteByte(MSG_ONE, TE_CSQC_RACE); - WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_NEXT); + WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_NEXT_QUALIFYING); WriteByte(MSG_ONE, cp); // checkpoint the player will be at next WriteShort(MSG_ONE, recordtime); WriteString(MSG_ONE, recordholder); @@ -68,85 +71,162 @@ void race_SendTime(entity e, float cp, float t, float tvalid) if(cp == 0) // finish line { float s; - s = PlayerScore_Add(e, SP_RACE_FASTEST, 0); - if(!s || t < s) - PlayerScore_Add(e, SP_RACE_FASTEST, t - s); - PlayerTeamScore_Add(e, SP_RACE_LAPS, ST_RACE_LAPS, 1); + if(g_race_qualifying) + { + s = PlayerScore_Add(e, SP_RACE_FASTEST, 0); + if(!s || t < s) + PlayerScore_Add(e, SP_RACE_FASTEST, t - s); + } + else + { + s = PlayerScore_Add(e, SP_RACE_TIME, 0); + PlayerScore_Add(e, SP_RACE_TIME, time - s); + PlayerTeamScore_Add(e, SP_RACE_LAPS, ST_RACE_LAPS, 1); + } } float recordtime; string recordholder; - if(tvalid) + if(g_race_qualifying) { - recordtime = race_checkpoint_records[cp]; - recordholder = strcat1(race_checkpoint_recordholders[cp]); // make a tempstring copy, as we'll possibly strunzone it! - if(recordholder == e.netname) - recordholder = ""; - - if(t < recordtime || recordtime == 0) + if(tvalid) { - race_checkpoint_records[cp] = t; - if(race_checkpoint_recordholders[cp]) - strunzone(race_checkpoint_recordholders[cp]); - race_checkpoint_recordholders[cp] = strzone(e.netname); - if(cp == 0) + recordtime = race_checkpoint_records[cp]; + recordholder = strcat1(race_checkpoint_recordholders[cp]); // make a tempstring copy, as we'll possibly strunzone it! + if(recordholder == e.netname) + recordholder = ""; + + if(t < recordtime || recordtime == 0) { - float grecordtime; - string grecordholder; - grecordtime = stof(db_get(ServerProgsDB, strcat(GetMapname(), "/racerecord/time"))); - grecordholder = db_get(ServerProgsDB, strcat(GetMapname(), "/racerecord/netname")); - if(grecordholder == e.netname) - grecordholder = ""; - if(grecordtime == 0) + race_checkpoint_records[cp] = t; + if(race_checkpoint_recordholders[cp]) + strunzone(race_checkpoint_recordholders[cp]); + race_checkpoint_recordholders[cp] = strzone(e.netname); + if(cp == 0) { - bprint(e.netname, "^7 set the all-time fastest lap record with ", mmsss(t), "\n"); - db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/time"), ftos(t)); - db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/netname"), e.netname); - } - else if(t < grecordtime) - { - if(grecordholder == "") - bprint(e.netname, "^7 broke his all-time fastest lap record with ", mmsss(t), "\n"); + float grecordtime; + string grecordholder; + grecordtime = stof(db_get(ServerProgsDB, strcat(GetMapname(), "/racerecord/time"))); + grecordholder = db_get(ServerProgsDB, strcat(GetMapname(), "/racerecord/netname")); + if(grecordholder == e.netname) + grecordholder = ""; + if(grecordtime == 0) + { + bprint(e.netname, "^7 set the all-time fastest lap record with ", mmsss(t), "\n"); + db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/time"), ftos(t)); + db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/netname"), e.netname); + } + else if(t < grecordtime) + { + if(grecordholder == "") + bprint(e.netname, "^7 broke his all-time fastest lap record with ", mmsss(t), "\n"); + else + bprint(e.netname, "^7 broke ", grecordholder, "^7's all-time fastest lap record with ", mmsss(t), "\n"); + db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/time"), ftos(t)); + db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/netname"), e.netname); + } else - bprint(e.netname, "^7 broke ", grecordholder, "^7's all-time fastest lap record with ", mmsss(t), "\n"); - db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/time"), ftos(t)); - db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/netname"), e.netname); + { + if(grecordholder == "") + bprint(e.netname, "^7's new fastest lap could not break his all-time fastest lap record of ", mmsss(grecordtime), "\n"); + else + bprint(e.netname, "^7's new fastest lap could not break ", grecordholder, "^7's all-time fastest lap record of ", mmsss(grecordtime), "\n"); + } } - else + + if(g_race_qualifying) { - if(grecordholder == "") - bprint(e.netname, "^7's new fastest lap could not break his all-time fastest lap record of ", mmsss(grecordtime), "\n"); - else - bprint(e.netname, "^7's new fastest lap could not break ", grecordholder, "^7's all-time fastest lap record of ", mmsss(grecordtime), "\n"); + entity p; + FOR_EACH_REALPLAYER(p) + if(p.race_checkpoint == cp) + race_SendNextCheckpoint(p); } } + } + else + { + // dummies + t = 0; + recordtime = 0; + recordholder = ""; + } - entity p; - FOR_EACH_REALPLAYER(p) - if(p.race_checkpoint == cp) - race_SendNextCheckpoint(p); + if(clienttype(e) == CLIENTTYPE_REAL) + { + msg_entity = e; + if(g_race_qualifying) + { + WriteByte(MSG_ONE, SVC_TEMPENTITY); + WriteByte(MSG_ONE, TE_CSQC_RACE); + WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_HIT_QUALIFYING); + WriteByte(MSG_ONE, cp); // checkpoint the player now is at + WriteShort(MSG_ONE, t); // time to that intermediate + WriteShort(MSG_ONE, recordtime); // previously best time + WriteString(MSG_ONE, recordholder); // record holder + } } } - else + else // RACE! Not Qualifying { - // dummies - t = 0; - recordtime = 0; - recordholder = ""; - } + float lself, lother, othtime; + entity oth; + oth = race_checkpoint_lastplayers[cp]; + if(oth) + { + lself = PlayerScore_Add(e, SP_RACE_LAPS, 0); + lother = race_checkpoint_lastlaps[cp]; + othtime = race_checkpoint_lasttimes[cp]; + } + else + lself = lother = othtime = 0; - if(clienttype(e) != CLIENTTYPE_REAL) - return; + if(clienttype(e) == CLIENTTYPE_REAL) + { + msg_entity = e; + WriteByte(MSG_ONE, SVC_TEMPENTITY); + WriteByte(MSG_ONE, TE_CSQC_RACE); + WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_HIT_RACE); + WriteByte(MSG_ONE, cp); // checkpoint the player now is at + if(e == oth) + { + WriteShort(MSG_ONE, 0); + WriteByte(MSG_ONE, 0); + WriteString(MSG_ONE, ""); + } + else + { + WriteShort(MSG_ONE, floor(10 * (time - race_checkpoint_lasttimes[cp]) + 0.5)); + WriteByte(MSG_ONE, lself - lother); + WriteString(MSG_ONE, oth.netname); // record holder + } + } - msg_entity = e; - WriteByte(MSG_ONE, SVC_TEMPENTITY); - WriteByte(MSG_ONE, TE_CSQC_RACE); - WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_HIT); - WriteByte(MSG_ONE, cp); // checkpoint the player now is at - WriteShort(MSG_ONE, t); // time to that intermediate - WriteShort(MSG_ONE, recordtime); // previously best time - WriteString(MSG_ONE, recordholder); // record holder + race_checkpoint_lastplayers[cp] = e; + race_checkpoint_lasttimes[cp] = time; + race_checkpoint_lastlaps[cp] = lself; + + if(clienttype(oth) == CLIENTTYPE_REAL) + { + msg_entity = oth; + WriteByte(MSG_ONE, SVC_TEMPENTITY); + WriteByte(MSG_ONE, TE_CSQC_RACE); + WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT); + WriteByte(MSG_ONE, cp); // checkpoint the player now is at + if(e == oth) + { + WriteShort(MSG_ONE, 0); + WriteByte(MSG_ONE, 0); + WriteString(MSG_ONE, ""); + } + else + { + WriteShort(MSG_ONE, floor(10 * (time - othtime) + 0.5)); + WriteByte(MSG_ONE, lother - lself); + WriteString(MSG_ONE, e.netname); // record holder + } + } + } } void race_ClearTime(entity e) @@ -177,7 +257,8 @@ void checkpoint_touch() if(!self.race_checkpoint) // finish line other.race_laptime = time; - race_SendNextCheckpoint(other); + if(g_race_qualifying) + race_SendNextCheckpoint(other); } else if(other.race_checkpoint == race_NextCheckpoint(self.race_checkpoint)) { diff --git a/data/qcsrc/server/scores_rules.qc b/data/qcsrc/server/scores_rules.qc index 890405da1..34f6323ff 100644 --- a/data/qcsrc/server/scores_rules.qc +++ b/data/qcsrc/server/scores_rules.qc @@ -124,6 +124,7 @@ void ScoreRules_kh(float teams) #define ST_RACE_LAPS 1 #define SP_RACE_LAPS 4 #define SP_RACE_FASTEST 5 +#define SP_RACE_TIME 5 void ScoreRules_race() { ScoreRules_basics(race_teams, 0); @@ -131,7 +132,7 @@ void ScoreRules_race() { ScoreInfo_SetLabel_TeamScore( ST_RACE_LAPS, "laps", SFL_SORT_PRIO_PRIMARY); ScoreInfo_SetLabel_PlayerScore(SP_RACE_LAPS, "laps", SFL_SORT_PRIO_PRIMARY); - ScoreInfo_SetLabel_PlayerScore(SP_RACE_FASTEST, "fastest", SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER | SFL_TIME); + ScoreInfo_SetLabel_PlayerScore(SP_RACE_TIME, "time", SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER | SFL_TIME); } else if(g_race_qualifying) { @@ -143,7 +144,7 @@ void ScoreRules_race() { ScoreInfo_SetLabel_TeamScore( ST_RACE_LAPS, "laps", 0); ScoreInfo_SetLabel_PlayerScore(SP_RACE_LAPS, "laps", SFL_SORT_PRIO_PRIMARY); - ScoreInfo_SetLabel_PlayerScore(SP_RACE_FASTEST, "fastest", SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER | SFL_TIME); + ScoreInfo_SetLabel_PlayerScore(SP_RACE_TIME, "time", SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER | SFL_TIME); } ScoreRules_basics_end(); } -- 2.39.2