1#ifndef GAME_SERVER_SAVE_H
2#define GAME_SERVER_SAVE_H
3
4#include <base/vmath.h>
5
6#include <engine/shared/protocol.h>
7
8#include <generated/protocol.h>
9
10#include <game/team_state.h>
11
12#include <optional>
13
14class IGameController;
15class CGameContext;
16class CGameWorld;
17class CCharacter;
18class CSaveTeam;
19
20enum
21{
22 RESCUEMODE_AUTO = 0,
23 RESCUEMODE_MANUAL,
24 NUM_RESCUEMODES
25};
26
27enum class ESaveResult
28{
29 SUCCESS,
30 TEAM_FLOCK,
31 TEAM_NOT_FOUND,
32 CHAR_NOT_FOUND,
33 NOT_STARTED,
34 TEAM_0_MODE,
35 DRAGGER_ACTIVE
36};
37
38class CSaveTee
39{
40public:
41 CSaveTee();
42 ~CSaveTee() = default;
43 void Save(CCharacter *pChr, bool AddPenalty = true);
44 bool Load(CCharacter *pChr, std::optional<int> Team = std::nullopt);
45 char *GetString(const CSaveTeam *pTeam);
46 // returns false if the tee could not be parsed or contains invalid values
47 bool FromString(const char *pString, int MembersCount);
48 void LoadHookedPlayer(const CSaveTeam *pTeam);
49 bool IsHooking() const;
50 vec2 GetPos() const { return m_Pos; }
51 const char *GetName() const { return m_aName; }
52 int GetClientId() const { return m_ClientId; }
53 void SetClientId(int ClientId) { m_ClientId = ClientId; }
54
55 enum
56 {
57 HIT_ALL = 0,
58 HAMMER_HIT_DISABLED = 1,
59 SHOTGUN_HIT_DISABLED = 2,
60 GRENADE_HIT_DISABLED = 4,
61 LASER_HIT_DISABLED = 8
62 };
63
64private:
65 int m_ClientId;
66
67 char m_aString[2048];
68 char m_aName[16];
69
70 int m_Alive;
71 int m_Paused;
72 int m_NeededFaketuning;
73
74 // Teamstuff
75 int m_TeeStarted;
76 int m_TeeFinished;
77 int m_IsSolo;
78
79 class CWeaponStat
80 {
81 public:
82 int m_AmmoRegenStart;
83 int m_Ammo;
84 int m_Ammocost;
85 int m_Got;
86 } m_aWeapons[NUM_WEAPONS];
87
88 // ninja
89 struct
90 {
91 vec2 m_ActivationDir;
92 int m_ActivationTick;
93 int m_CurrentMoveTime;
94 int m_OldVelAmount;
95 } m_Ninja;
96
97 int m_LastWeapon;
98 int m_QueuedWeapon;
99
100 int m_EndlessJump;
101 int m_Jetpack;
102 int m_NinjaJetpack;
103 int m_FreezeTime;
104 int m_FreezeStart;
105 int m_DeepFrozen;
106 int m_LiveFrozen;
107 int m_EndlessHook;
108 int m_DDRaceState;
109
110 int m_HitDisabledFlags;
111 int m_CollisionEnabled;
112 int m_TuneZone;
113 int m_TuneZoneOld;
114 int m_HookHitEnabled;
115 int m_Time;
116 vec2 m_Pos;
117 vec2 m_PrevPos;
118 int m_TeleCheckpoint;
119 int m_LastPenalty;
120
121 int m_TimeCpBroadcastEndTime;
122 int m_LastTimeCp;
123 int m_LastTimeCpBroadcasted;
124 float m_aCurrentTimeCp[MAX_CHECKPOINTS];
125
126 int m_NotEligibleForFinish;
127
128 int m_HasTelegunGun;
129 int m_HasTelegunGrenade;
130 int m_HasTelegunLaser;
131
132 // Core
133 vec2 m_CorePos;
134 vec2 m_Vel;
135 int m_ActiveWeapon;
136 int m_Jumped;
137 int m_JumpedTotal;
138 int m_Jumps;
139 vec2 m_HookPos;
140 vec2 m_HookDir;
141 vec2 m_HookTeleBase;
142 int m_HookTick;
143 int m_HookState;
144 int m_HookedPlayer;
145 int m_NewHook;
146
147 // player input
148 int m_InputDirection;
149 int m_InputJump;
150 int m_InputFire;
151 int m_InputHook;
152
153 int m_ReloadTimer;
154
155 char m_aGameUuid[UUID_MAXSTRSIZE];
156};
157
158class CSaveHotReloadTee
159{
160public:
161 CSaveHotReloadTee() = default;
162 ~CSaveHotReloadTee() = default;
163 void Save(CCharacter *pChr, bool AddPenalty = true);
164 bool Load(CCharacter *pChr, int Team);
165
166private:
167 CSaveTee m_SaveTee;
168 bool m_Super;
169 bool m_Invincible;
170 CSaveTee m_SavedTeleTee;
171 std::optional<CSaveTee> m_LastDeath;
172};
173
174class CSaveTeam
175{
176public:
177 CSaveTeam();
178 ~CSaveTeam();
179 char *GetString();
180 int GetMembersCount() const { return m_MembersCount; }
181 // MatchPlayers has to be called afterwards
182 int FromString(const char *pString);
183 // returns true if a team can load, otherwise writes a nice error Message in pMessage
184 bool MatchPlayers(const char (*paNames)[MAX_NAME_LENGTH], const int *pClientId, int NumPlayer, char *pMessage, int MessageLen) const;
185 ESaveResult Save(CGameContext *pGameServer, int Team, bool Dry = false, bool Force = false);
186 bool Load(CGameContext *pGameServer, int Team, bool KeepCurrentWeakStrong, bool IgnorePlayers = false);
187
188 CSaveTee *m_pSavedTees = nullptr;
189
190 // returns true if an error occurred
191 static bool HandleSaveError(ESaveResult Result, int ClientId, CGameContext *pGameContext);
192
193private:
194 CCharacter *MatchCharacter(CGameContext *pGameServer, int ClientId, int SaveId, bool KeepCurrentCharacter) const;
195
196 char m_aString[65536];
197
198 struct SSimpleSwitchers
199 {
200 int m_Status;
201 int m_EndTime;
202 int m_Type;
203 };
204 SSimpleSwitchers *m_pSwitchers = nullptr;
205
206 ETeamState m_TeamState = ETeamState::EMPTY;
207 int m_MembersCount = 0;
208 int m_HighestSwitchNumber = 0;
209 int m_TeamLocked = 0;
210 int m_Practice = 0;
211};
212
213#endif // GAME_SERVER_SAVE_H
214