1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3#ifndef GAME_SERVER_ENTITIES_CHARACTER_H
4#define GAME_SERVER_ENTITIES_CHARACTER_H
5
6#include <game/race_state.h>
7#include <game/server/entity.h>
8#include <game/server/save.h>
9
10class CPlayer;
11class CGameTeams;
12class CGameWorld;
13class IAntibot;
14struct CAntibotCharacterData;
15
16enum
17{
18 FAKETUNE_FREEZE = 1 << 0,
19 FAKETUNE_SOLO = 1 << 1,
20 FAKETUNE_NOJUMP = 1 << 2,
21 FAKETUNE_NOCOLL = 1 << 3,
22 FAKETUNE_NOHOOK = 1 << 4,
23 FAKETUNE_JETPACK = 1 << 5,
24 FAKETUNE_NOHAMMER = 1 << 6,
25};
26
27class CCharacter : public CEntity
28{
29 MACRO_ALLOC_POOL_ID()
30
31 // need to use core
32 friend class CSaveTee;
33 friend class CSaveHotReloadTee;
34
35public:
36 CCharacter(CGameWorld *pWorld, CNetObj_PlayerInput LastInput);
37
38 void Reset() override;
39 void Destroy() override;
40 void PreTick();
41 void Tick() override;
42 void TickDeferred() override;
43 void TickPaused() override;
44 void Snap(int SnappingClient) override;
45 void SwapClients(int Client1, int Client2) override;
46
47 void PostGlobalSnap();
48
49 bool CanSnapCharacter(int SnappingClient);
50 bool IsSnappingCharacterInView(int SnappingClientId);
51
52 bool IsGrounded();
53
54 void SetWeapon(int W);
55 void SetJetpack(bool Active);
56 void SetEndlessJump(bool Active);
57 void SetJumps(int Jumps);
58 void SetSolo(bool Solo);
59 void SetSuper(bool Super);
60 void SetInvincible(bool Invincible);
61 void SetCollisionDisabled(bool CollisionDisabled);
62 void SetHookHitDisabled(bool HookHitDisabled);
63 void SetLiveFrozen(bool Active);
64 void SetDeepFrozen(bool Active);
65 void HandleWeaponSwitch();
66 void DoWeaponSwitch();
67
68 void HandleWeapons();
69 void HandleNinja();
70 void HandleJetpack();
71
72 void OnPredictedInput(const CNetObj_PlayerInput *pNewInput);
73 void OnDirectInput(const CNetObj_PlayerInput *pNewInput);
74 void ReleaseHook();
75 void ResetHook();
76 void ResetInput();
77 void FireWeapon();
78
79 void Die(int Killer, int Weapon, bool SendKillMsg = true);
80 bool TakeDamage(vec2 Force, int Dmg, int From, int Weapon);
81 void SendDeathMessageIfNotInLockedTeam(int Killer, int Weapon, int ModeSpecial);
82 void CancelSwapRequests();
83
84 bool Spawn(class CPlayer *pPlayer, vec2 Pos);
85 bool Remove();
86
87 bool IncreaseHealth(int Amount);
88 bool IncreaseArmor(int Amount);
89
90 void GiveWeapon(int Weapon, bool Remove = false);
91 void GiveNinja();
92 void RemoveNinja();
93 void SetEndlessHook(bool Enable);
94
95 void SetEmote(int Emote, int Tick);
96 int DetermineEyeEmote();
97
98 void Rescue();
99
100 int NeededFaketuning() const { return m_NeededFaketuning; }
101 bool IsAlive() const { return m_Alive; }
102 bool IsPaused() const { return m_Paused; }
103 CPlayer *GetPlayer() { return m_pPlayer; }
104 const CPlayer *GetPlayer() const { return m_pPlayer; }
105 CClientMask TeamMask();
106
107 void SetPosition(const vec2 &Position);
108 void Move(vec2 RelPos);
109
110 void ResetVelocity();
111 void SetVelocity(vec2 NewVelocity);
112 void SetRawVelocity(vec2 NewVelocity);
113 void AddVelocity(vec2 Addition);
114 void ApplyMoveRestrictions();
115
116private:
117 // player controlling this character
118 class CPlayer *m_pPlayer;
119
120 bool m_Alive;
121 bool m_Paused;
122 int m_PausedTick;
123 int m_NeededFaketuning;
124
125 // weapon info
126 int m_aHitObjects[MAX_CLIENTS];
127 int m_NumObjectsHit;
128
129 int m_LastWeapon;
130 int m_QueuedWeapon;
131
132 int m_ReloadTimer;
133 int m_AttackTick;
134
135 int m_MoveRestrictions;
136
137 int m_DamageTaken;
138
139 int m_EmoteType;
140 int m_EmoteStop;
141
142 // last tick that the player took any action ie some input
143 int m_LastAction;
144
145 // these are non-heldback inputs
146 CNetObj_PlayerInput m_LatestPrevPrevInput;
147 CNetObj_PlayerInput m_LatestPrevInput;
148 CNetObj_PlayerInput m_LatestInput;
149
150 // input
151 CNetObj_PlayerInput m_PrevInput;
152 CNetObj_PlayerInput m_Input;
153 CNetObj_PlayerInput m_SavedInput;
154 int m_NumInputs;
155
156 int m_DamageTakenTick;
157
158 int m_Health;
159 int m_Armor;
160 int m_TriggeredEvents7;
161
162 // the player core for the physics
163 CCharacterCore m_Core;
164 CGameTeams *m_pTeams = nullptr;
165
166 // info for dead reckoning
167 int m_ReckoningTick; // tick that we are performing dead reckoning From
168 CCharacterCore m_SendCore; // core that we should send
169 CCharacterCore m_ReckoningCore; // the dead reckoning core
170
171 // DDRace
172
173 void SnapCharacter(int SnappingClient, int Id);
174 static bool IsSwitchActiveCb(unsigned char Number, void *pUser);
175 void SetTimeCheckpoint(int TimeCheckpoint);
176 void HandleTiles(int Index);
177 float m_Time;
178 int m_LastBroadcast;
179 void DDRaceInit();
180 void HandleSkippableTiles(int Index);
181 void ForceSetRescue(int RescueMode);
182 void DDRaceTick();
183 void DDRacePostCoreTick();
184 void HandleBroadcast();
185 void HandleTuneLayer();
186 void SendZoneMsgs();
187 IAntibot *Antibot();
188
189 bool m_SetSavePos[NUM_RESCUEMODES];
190 CSaveTee m_RescueTee[NUM_RESCUEMODES];
191
192public:
193 CGameTeams *Teams() { return m_pTeams; }
194 void SetTeams(CGameTeams *pTeams);
195 bool TrySetRescue(int RescueMode);
196
197 void FillAntibot(CAntibotCharacterData *pData);
198 void Pause(bool Pause);
199 bool Freeze(int Seconds);
200 bool Freeze();
201 bool Unfreeze();
202 void GiveAllWeapons();
203 void ResetPickups();
204 void ResetJumps();
205 ERaceState m_DDRaceState;
206 int Team();
207 bool CanCollide(int ClientId) override;
208 bool SameTeam(int ClientId);
209 void StopRecording();
210 bool m_NinjaJetpack;
211 int m_TeamBeforeSuper;
212 int m_FreezeTime;
213 bool m_FrozenLastTick;
214 int m_TuneZone;
215 int m_TuneZoneOld;
216 int m_PainSoundTimer;
217 int m_LastMove;
218 int m_StartTime;
219 vec2 m_PrevPos;
220 int m_TeleCheckpoint;
221
222 int m_TimeCpBroadcastEndTick;
223 int m_LastTimeCp;
224 int m_LastTimeCpBroadcasted;
225 float m_aCurrentTimeCp[MAX_CHECKPOINTS];
226
227 int m_TileIndex;
228 int m_TileFIndex;
229
230 int64_t m_LastStartWarning;
231 int64_t m_LastRescue;
232 bool m_LastRefillJumps;
233 bool m_LastPenalty;
234 bool m_LastBonus;
235 vec2 m_TeleGunPos;
236 bool m_TeleGunTeleport;
237 bool m_IsBlueTeleGunTeleport;
238 int m_StrongWeakId;
239
240 int m_SpawnTick;
241 int m_WeaponChangeTick;
242
243 // Setters/Getters because i don't want to modify vanilla vars access modifiers
244 int GetLastWeapon() const { return m_LastWeapon; }
245 void SetLastWeapon(int LastWeap) { m_LastWeapon = LastWeap; }
246 int GetActiveWeapon() const { return m_Core.m_ActiveWeapon; }
247 void SetActiveWeapon(int ActiveWeap) { m_Core.m_ActiveWeapon = ActiveWeap; }
248 void SetLastAction(int LastAction) { m_LastAction = LastAction; }
249 int GetArmor() const { return m_Armor; }
250 void SetArmor(int Armor) { m_Armor = Armor; }
251 CCharacterCore GetCore() { return m_Core; }
252 void SetCore(const CCharacterCore &Core) { m_Core = Core; }
253 const CCharacterCore *Core() const { return &m_Core; }
254 bool GetWeaponGot(int Type) { return m_Core.m_aWeapons[Type].m_Got; }
255 void SetWeaponGot(int Type, bool Value) { m_Core.m_aWeapons[Type].m_Got = Value; }
256 int GetWeaponAmmo(int Type) { return m_Core.m_aWeapons[Type].m_Ammo; }
257 void SetWeaponAmmo(int Type, int Value) { m_Core.m_aWeapons[Type].m_Ammo = Value; }
258 void SetNinjaActivationDir(vec2 ActivationDir) { m_Core.m_Ninja.m_ActivationDir = ActivationDir; }
259 void SetNinjaActivationTick(int ActivationTick) { m_Core.m_Ninja.m_ActivationTick = ActivationTick; }
260 void SetNinjaCurrentMoveTime(int CurrentMoveTime) { m_Core.m_Ninja.m_CurrentMoveTime = CurrentMoveTime; }
261
262 int GetLastAction() const { return m_LastAction; }
263
264 bool HasTelegunGun() const { return m_Core.m_HasTelegunGun; }
265 bool HasTelegunGrenade() const { return m_Core.m_HasTelegunGrenade; }
266 bool HasTelegunLaser() const { return m_Core.m_HasTelegunLaser; }
267
268 bool HammerHitDisabled() const { return m_Core.m_HammerHitDisabled; }
269 bool ShotgunHitDisabled() const { return m_Core.m_ShotgunHitDisabled; }
270 bool LaserHitDisabled() const { return m_Core.m_LaserHitDisabled; }
271 bool GrenadeHitDisabled() const { return m_Core.m_GrenadeHitDisabled; }
272
273 void SetHammerHitDisabled(bool HammerHitDisabled) { m_Core.m_HammerHitDisabled = HammerHitDisabled; }
274 void SetShotgunHitDisabled(bool ShotgunHitDisabled) { m_Core.m_ShotgunHitDisabled = ShotgunHitDisabled; }
275 void SetGrenadeHitDisabled(bool GrenadeHitDisabled) { m_Core.m_GrenadeHitDisabled = GrenadeHitDisabled; }
276 void SetLaserHitDisabled(bool LaserHitDisabled) { m_Core.m_LaserHitDisabled = LaserHitDisabled; }
277
278 bool IsSuper() const { return m_Core.m_Super; }
279
280 CSaveTee &GetLastRescueTeeRef(int Mode = RESCUEMODE_AUTO) { return m_RescueTee[Mode]; }
281 CTuningParams *GetTuning(int Zone) { return &TuningList()[Zone]; }
282};
283
284#endif
285