1#include <cctype>
2#include <list>
3
4#include <game/client/gameclient.h>
5#include <game/mapitems.h>
6
7#include "race.h"
8
9int CRaceHelper::ms_aFlagIndex[2] = {-1, -1};
10
11int CRaceHelper::TimeFromSecondsStr(const char *pStr)
12{
13 while(*pStr == ' ') // skip leading spaces
14 pStr++;
15 if(!isdigit(*pStr))
16 return -1;
17 int Time = str_toint(str: pStr) * 1000;
18 while(isdigit(*pStr))
19 pStr++;
20 if(*pStr == '.' || *pStr == ',')
21 {
22 pStr++;
23 static const int s_aMult[3] = {100, 10, 1};
24 for(size_t i = 0; i < std::size(s_aMult) && isdigit(pStr[i]); i++)
25 Time += (pStr[i] - '0') * s_aMult[i];
26 }
27 return Time;
28}
29
30int CRaceHelper::TimeFromStr(const char *pStr)
31{
32 static const char *const s_pMinutesStr = " minute(s) ";
33 static const char *const s_pSecondsStr = " second(s)";
34
35 const char *pSeconds = str_find(haystack: pStr, needle: s_pSecondsStr);
36 if(!pSeconds)
37 return -1;
38
39 const char *pMinutes = str_find(haystack: pStr, needle: s_pMinutesStr);
40 if(pMinutes)
41 {
42 while(*pStr == ' ') // skip leading spaces
43 pStr++;
44 int SecondsTime = TimeFromSecondsStr(pStr: pMinutes + str_length(str: s_pMinutesStr));
45 if(SecondsTime == -1 || !isdigit(*pStr))
46 return -1;
47 return str_toint(str: pStr) * 60 * 1000 + SecondsTime;
48 }
49 else
50 return TimeFromSecondsStr(pStr);
51}
52
53int CRaceHelper::TimeFromFinishMessage(const char *pStr, char *pNameBuf, int NameBufSize)
54{
55 static const char *const s_pFinishedStr = " finished in: ";
56 const char *pFinished = str_find(haystack: pStr, needle: s_pFinishedStr);
57 if(!pFinished)
58 return -1;
59
60 int FinishedPos = pFinished - pStr;
61 if(FinishedPos == 0 || FinishedPos >= NameBufSize)
62 return -1;
63
64 str_copy(dst: pNameBuf, src: pStr, dst_size: FinishedPos + 1);
65
66 return TimeFromStr(pStr: pFinished + str_length(str: s_pFinishedStr));
67}
68
69bool CRaceHelper::IsStart(CGameClient *pClient, vec2 Prev, vec2 Pos)
70{
71 CCollision *pCollision = pClient->Collision();
72 if(pClient->m_GameInfo.m_FlagStartsRace)
73 {
74 int EnemyTeam = pClient->m_aClients[pClient->m_Snap.m_LocalClientId].m_Team ^ 1;
75 return ms_aFlagIndex[EnemyTeam] != -1 && distance(a: Pos, b: pCollision->GetPos(Index: ms_aFlagIndex[EnemyTeam])) < 32;
76 }
77 else
78 {
79 std::vector<int> vIndices = pCollision->GetMapIndices(PrevPos: Prev, Pos);
80 if(!vIndices.empty())
81 for(int &Indice : vIndices)
82 {
83 if(pCollision->GetTileIndex(Index: Indice) == TILE_START)
84 return true;
85 if(pCollision->GetFTileIndex(Index: Indice) == TILE_START)
86 return true;
87 }
88 else
89 {
90 if(pCollision->GetTileIndex(Index: pCollision->GetPureMapIndex(Pos)) == TILE_START)
91 return true;
92 if(pCollision->GetFTileIndex(Index: pCollision->GetPureMapIndex(Pos)) == TILE_START)
93 return true;
94 }
95 }
96 return false;
97}
98