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