registercvar("cl_spawn_near_teammate", "1");
+ registercvar("cl_race_cptimes_onlyself", "0");
+
if(autocvar_cl_lockview)
cvar_set("cl_lockview", "0");
race_penaltyaccumulator = 0;
race_laptime = time; // valid
}
+ break;
+ case RACE_NET_CHECKPOINT_HIT_SELF_QUALIFYING:
+ race_checkpoint = ReadByte();
+ race_time = ReadInt24_t();
+ race_previousbesttime = ReadInt24_t();
+ if(race_previousbestname)
+ strunzone(race_previousbestname);
+ race_previousbestname = strzone(""); // handled by MakeRaceString
+
+ race_checkpointtime = time;
+ if(race_checkpoint == 0 || race_checkpoint == 254)
+ {
+ race_penaltyaccumulator = 0;
+ race_laptime = time; // valid
+ }
break;
case RACE_NET_CHECKPOINT_CLEAR:
race_nextbestname = strzone(ReadString());
break;
+ case RACE_NET_CHECKPOINT_NEXT_SELF_QUALIFYING:
+ race_nextcheckpoint = ReadByte();
+
+ race_nextbesttime = ReadInt24_t();
+ if(race_nextbestname)
+ strunzone(race_nextbestname);
+ race_nextbestname = strzone(""); // handled by MakeRaceString
+ break;
+
case RACE_NET_CHECKPOINT_HIT_RACE:
race_mycheckpoint = ReadByte();
race_mycheckpointtime = time;
race_mycheckpointlapsdelta -= 256;
if(race_mycheckpointenemy)
strunzone(race_mycheckpointenemy);
- race_mycheckpointenemy = strzone(ReadString());
+ int who = ReadByte();
+ if(who)
+ race_mycheckpointenemy = strzone(entcs_GetName(who - 1));
+ else
+ race_mycheckpointenemy = strzone(""); // TODO: maybe string_null works fine here?
break;
case RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT:
race_othercheckpointlapsdelta -= 256;
if(race_othercheckpointenemy)
strunzone(race_othercheckpointenemy);
- race_othercheckpointenemy = strzone(ReadString());
+ int what = ReadByte();
+ if(what)
+ race_othercheckpointenemy = strzone(entcs_GetName(what - 1));
+ else
+ race_othercheckpointenemy = strzone(""); // TODO: maybe string_null works fine here?
break;
case RACE_NET_PENALTY_RACE:
float race_checkpoint_lastlaps[MAX_CHECKPOINTS];
entity race_checkpoint_lastplayers[MAX_CHECKPOINTS];
+.float race_checkpoint_record[MAX_CHECKPOINTS];
+
float race_highest_checkpoint;
float race_timed_checkpoint;
void race_SendNextCheckpoint(entity e, float spec) // qualifying only
{
- float recordtime;
- string recordholder;
- float cp;
-
if(!e.race_laptime)
return;
- cp = e.race_checkpoint;
- recordtime = race_checkpoint_records[cp];
- recordholder = race_checkpoint_recordholders[cp];
+ int cp = e.race_checkpoint;
+ float recordtime = race_checkpoint_records[cp];
+ string recordholder = race_checkpoint_recordholders[cp];
if(recordholder == e.netname)
recordholder = "";
if(!IS_REAL_CLIENT(e))
return;
- if(!spec)
+ if(!spec && !e.cvar_cl_race_cptimes_onlyself) // don't show spectators the player's personal time
msg_entity = e;
WRITESPECTATABLE_MSG_ONE(msg_entity, {
WriteHeader(MSG_ONE, TE_CSQC_RACE);
WriteInt24_t(MSG_ONE, recordtime);
WriteString(MSG_ONE, recordholder);
});
+
+ if(!spec && e.cvar_cl_race_cptimes_onlyself) // don't send to spectators!
+ {
+ recordtime = e.race_checkpoint_record[cp];
+
+ // not spectatable
+ msg_entity = e;
+ WriteHeader(MSG_ONE, TE_CSQC_RACE);
+ WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_NEXT_SELF_QUALIFYING);
+ WriteByte(MSG_ONE, race_CheckpointNetworkID(cp)); // checkpoint the player will be at next
+ WriteInt24_t(MSG_ONE, recordtime);
+ }
}
void race_send_recordtime(float msg)
}
}
- float recordtime;
- string recordholder;
if(g_race_qualifying)
{
+ float recordtime;
+ float myrecordtime;
+ string recordholder;
+
if(tvalid)
{
recordtime = race_checkpoint_records[cp];
+ myrecordtime = e.race_checkpoint_record[cp];
recordholder = strcat1(race_checkpoint_recordholders[cp]); // make a tempstring copy, as we'll possibly strunzone it!
if(recordholder == e.netname)
recordholder = "";
strunzone(race_checkpoint_recordholders[cp]);
race_checkpoint_recordholders[cp] = strzone(e.netname);
if(g_race_qualifying)
- {
FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && it.race_checkpoint == cp, LAMBDA(race_SendNextCheckpoint(it, 0)));
- }
}
+
+ if(t < myrecordtime || myrecordtime == 0)
+ e.race_checkpoint_record[cp] = t; // resending done below
}
}
else
// dummies
t = 0;
recordtime = 0;
+ myrecordtime = 0;
recordholder = "";
}
msg_entity = e;
if(g_race_qualifying)
{
- WRITESPECTATABLE_MSG_ONE(msg_entity, {
+ WRITESPECTATABLE_MSG_ONE(e, {
+ if(it == e && e.cvar_cl_race_cptimes_onlyself)
+ continue;
WriteHeader(MSG_ONE, TE_CSQC_RACE);
WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_HIT_QUALIFYING);
WriteByte(MSG_ONE, race_CheckpointNetworkID(cp)); // checkpoint the player now is at
WriteInt24_t(MSG_ONE, recordtime); // previously best time
WriteString(MSG_ONE, recordholder); // record holder
});
+
+ if(e.cvar_cl_race_cptimes_onlyself)
+ {
+ msg_entity = e;
+ WriteHeader(MSG_ONE, TE_CSQC_RACE);
+ WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_HIT_SELF_QUALIFYING);
+ WriteByte(MSG_ONE, race_CheckpointNetworkID(cp)); // checkpoint the player now is at
+ WriteInt24_t(MSG_ONE, t); // time to that intermediate
+ WriteInt24_t(MSG_ONE, myrecordtime); // previously best time
+ }
}
}
}
else // RACE! Not Qualifying
{
float mylaps, lother, othtime;
- entity oth;
- oth = race_checkpoint_lastplayers[cp];
+ entity oth = race_checkpoint_lastplayers[cp];
if(oth)
{
mylaps = PlayerScore_Add(e, SP_RACE_LAPS, 0);
{
WriteInt24_t(MSG_ONE, 0);
WriteByte(MSG_ONE, 0);
- WriteString(MSG_ONE, "");
+ WriteByte(MSG_ONE, 0);
}
else
{
WriteInt24_t(MSG_ONE, TIME_ENCODE(time - race_checkpoint_lasttimes[cp]));
WriteByte(MSG_ONE, mylaps - lother);
- WriteString(MSG_ONE, oth.netname); // record holder
+ WriteByte(MSG_ONE, etof(oth)); // record holder
}
});
}
{
WriteInt24_t(MSG_ONE, 0);
WriteByte(MSG_ONE, 0);
- WriteString(MSG_ONE, "");
+ WriteByte(MSG_ONE, 0);
}
else
{
WriteInt24_t(MSG_ONE, TIME_ENCODE(time - othtime));
WriteByte(MSG_ONE, lother - mylaps);
- WriteString(MSG_ONE, e.netname); // record holder
+ WriteByte(MSG_ONE, etof(e) - 1); // record holder
}
});
}