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 int m_LastNoAmmoSound;
143
144 // these are non-heldback inputs
145 CNetObj_PlayerInput m_LatestPrevPrevInput;
146 CNetObj_PlayerInput m_LatestPrevInput;
147 CNetObj_PlayerInput m_LatestInput;
148
149 // input
150 CNetObj_PlayerInput m_PrevInput;
151 CNetObj_PlayerInput m_Input;
152 CNetObj_PlayerInput m_SavedInput;
153 int m_NumInputs;
154
155 int m_DamageTakenTick;
156
157 int m_Health;
158 int m_Armor;
159 int m_TriggeredEvents7;
160
161 // the player core for the physics
162 CCharacterCore m_Core;
163 CGameTeams *m_pTeams = nullptr;
164
165 // info for dead reckoning
166 int m_ReckoningTick; // tick that we are performing dead reckoning From
167 CCharacterCore m_SendCore; // core that we should send
168 CCharacterCore m_ReckoningCore; // the dead reckoning core
169
170 // DDRace
171
172 void SnapCharacter(int SnappingClient, int Id);
173 static bool IsSwitchActiveCb(int Number, void *pUser);
174 void SetTimeCheckpoint(int TimeCheckpoint);
175 void HandleTiles(int Index);
176 float m_Time;
177 int m_LastBroadcast;
178 void DDRaceInit();
179 void HandleSkippableTiles(int Index);
180 void ForceSetRescue(int RescueMode);
181 void DDRaceTick();
182 void DDRacePostCoreTick();
183 void HandleBroadcast();
184 void HandleTuneLayer();
185 void SendZoneMsgs();
186 IAntibot *Antibot();
187
188 bool m_SetSavePos[NUM_RESCUEMODES];
189 CSaveTee m_RescueTee[NUM_RESCUEMODES];
190
191public:
192 CGameTeams *Teams() { return m_pTeams; }
193 void SetTeams(CGameTeams *pTeams);
194 bool TrySetRescue(int RescueMode);
195
196 void FillAntibot(CAntibotCharacterData *pData);
197 void Pause(bool Pause);
198 bool Freeze(int Seconds);
199 bool Freeze();
200 bool UnFreeze();
201 void GiveAllWeapons();
202 void ResetPickups();
203 void ResetJumps();
204 ERaceState m_DDRaceState;
205 int Team();
206 bool CanCollide(int ClientId) override;
207 bool SameTeam(int ClientId);
208 void StopRecording();
209 bool m_NinjaJetpack;
210 int m_TeamBeforeSuper;
211 int m_FreezeTime;
212 bool m_FrozenLastTick;
213 int m_TuneZone;
214 int m_TuneZoneOld;
215 int m_PainSoundTimer;
216 int m_LastMove;
217 int m_StartTime;
218 vec2 m_PrevPos;
219 int m_TeleCheckpoint;
220
221 int m_TimeCpBroadcastEndTick;
222 int m_LastTimeCp;
223 int m_LastTimeCpBroadcasted;
224 float m_aCurrentTimeCp[MAX_CHECKPOINTS];
225
226 int m_TileIndex;
227 int m_TileFIndex;
228
229 int64_t m_LastStartWarning;
230 int64_t m_LastRescue;
231 bool m_LastRefillJumps;
232 bool m_LastPenalty;
233 bool m_LastBonus;
234 vec2 m_TeleGunPos;
235 bool m_TeleGunTeleport;
236 bool m_IsBlueTeleGunTeleport;
237 int m_StrongWeakId;
238
239 int m_SpawnTick;
240 int m_WeaponChangeTick;
241
242 // Setters/Getters because i don't want to modify vanilla vars access modifiers
243 int GetLastWeapon() const { return m_LastWeapon; }
244 void SetLastWeapon(int LastWeap) { m_LastWeapon = LastWeap; }
245 int GetActiveWeapon() const { return m_Core.m_ActiveWeapon; }
246 void SetActiveWeapon(int ActiveWeap) { m_Core.m_ActiveWeapon = ActiveWeap; }
247 void SetLastAction(int LastAction) { m_LastAction = LastAction; }
248 int GetArmor() const { return m_Armor; }
249 void SetArmor(int Armor) { m_Armor = Armor; }
250 CCharacterCore GetCore() { return m_Core; }
251 void SetCore(const CCharacterCore &Core) { m_Core = Core; }
252 const CCharacterCore *Core() const { return &m_Core; }
253 bool GetWeaponGot(int Type) { return m_Core.m_aWeapons[Type].m_Got; }
254 void SetWeaponGot(int Type, bool Value) { m_Core.m_aWeapons[Type].m_Got = Value; }
255 int GetWeaponAmmo(int Type) { return m_Core.m_aWeapons[Type].m_Ammo; }
256 void SetWeaponAmmo(int Type, int Value) { m_Core.m_aWeapons[Type].m_Ammo = Value; }
257 void SetNinjaActivationDir(vec2 ActivationDir) { m_Core.m_Ninja.m_ActivationDir = ActivationDir; }
258 void SetNinjaActivationTick(int ActivationTick) { m_Core.m_Ninja.m_ActivationTick = ActivationTick; }
259 void SetNinjaCurrentMoveTime(int CurrentMoveTime) { m_Core.m_Ninja.m_CurrentMoveTime = CurrentMoveTime; }
260
261 int GetLastAction() const { return m_LastAction; }
262
263 bool HasTelegunGun() const { return m_Core.m_HasTelegunGun; }
264 bool HasTelegunGrenade() const { return m_Core.m_HasTelegunGrenade; }
265 bool HasTelegunLaser() const { return m_Core.m_HasTelegunLaser; }
266
267 bool HammerHitDisabled() const { return m_Core.m_HammerHitDisabled; }
268 bool ShotgunHitDisabled() const { return m_Core.m_ShotgunHitDisabled; }
269 bool LaserHitDisabled() const { return m_Core.m_LaserHitDisabled; }
270 bool GrenadeHitDisabled() const { return m_Core.m_GrenadeHitDisabled; }
271
272 void SetHammerHitDisabled(bool HammerHitDisabled) { m_Core.m_HammerHitDisabled = HammerHitDisabled; }
273 void SetShotgunHitDisabled(bool ShotgunHitDisabled) { m_Core.m_ShotgunHitDisabled = ShotgunHitDisabled; }
274 void SetGrenadeHitDisabled(bool GrenadeHitDisabled) { m_Core.m_GrenadeHitDisabled = GrenadeHitDisabled; }
275 void SetLaserHitDisabled(bool LaserHitDisabled) { m_Core.m_LaserHitDisabled = LaserHitDisabled; }
276
277 bool IsSuper() const { return m_Core.m_Super; }
278
279 CSaveTee &GetLastRescueTeeRef(int Mode = RESCUEMODE_AUTO) { return m_RescueTee[Mode]; }
280 CTuningParams *GetTuning(int Zone) { return &TuningList()[Zone]; }
281};
282
283#endif
284