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_CLIENT_GAMECLIENT_H
4#define GAME_CLIENT_GAMECLIENT_H
5
6#include "render.h"
7#include <base/color.h>
8#include <base/vmath.h>
9#include <engine/client.h>
10#include <engine/console.h>
11#include <engine/shared/config.h>
12
13#include <game/collision.h>
14#include <game/gamecore.h>
15#include <game/layers.h>
16#include <game/teamscore.h>
17
18#include <game/client/prediction/gameworld.h>
19
20// components
21#include "components/background.h"
22#include "components/binds.h"
23#include "components/broadcast.h"
24#include "components/camera.h"
25#include "components/chat.h"
26#include "components/console.h"
27#include "components/controls.h"
28#include "components/countryflags.h"
29#include "components/damageind.h"
30#include "components/debughud.h"
31#include "components/effects.h"
32#include "components/emoticon.h"
33#include "components/flow.h"
34#include "components/freezebars.h"
35#include "components/ghost.h"
36#include "components/hud.h"
37#include "components/infomessages.h"
38#include "components/items.h"
39#include "components/mapimages.h"
40#include "components/maplayers.h"
41#include "components/mapsounds.h"
42#include "components/menu_background.h"
43#include "components/menus.h"
44#include "components/motd.h"
45#include "components/nameplates.h"
46#include "components/particles.h"
47#include "components/players.h"
48#include "components/race_demo.h"
49#include "components/scoreboard.h"
50#include "components/skins.h"
51#include "components/sounds.h"
52#include "components/spectator.h"
53#include "components/statboard.h"
54#include "components/tooltips.h"
55#include "components/voting.h"
56
57class CGameInfo
58{
59public:
60 bool m_FlagStartsRace;
61 bool m_TimeScore;
62 bool m_UnlimitedAmmo;
63 bool m_DDRaceRecordMessage;
64 bool m_RaceRecordMessage;
65 bool m_RaceSounds;
66
67 bool m_AllowEyeWheel;
68 bool m_AllowHookColl;
69 bool m_AllowZoom;
70
71 bool m_BugDDRaceGhost;
72 bool m_BugDDRaceInput;
73 bool m_BugFNGLaserRange;
74 bool m_BugVanillaBounce;
75
76 bool m_PredictFNG;
77 bool m_PredictDDRace;
78 bool m_PredictDDRaceTiles;
79 bool m_PredictVanilla;
80
81 bool m_EntitiesDDNet;
82 bool m_EntitiesDDRace;
83 bool m_EntitiesRace;
84 bool m_EntitiesFNG;
85 bool m_EntitiesVanilla;
86 bool m_EntitiesBW;
87 bool m_EntitiesFDDrace;
88
89 bool m_Race;
90
91 bool m_DontMaskEntities;
92 bool m_AllowXSkins;
93
94 bool m_HudHealthArmor;
95 bool m_HudAmmo;
96 bool m_HudDDRace;
97
98 bool m_NoWeakHookAndBounce;
99 bool m_NoSkinChangeForFrozen;
100};
101
102class CSnapEntities
103{
104public:
105 IClient::CSnapItem m_Item;
106 const void *m_pData;
107 const CNetObj_EntityEx *m_pDataEx;
108};
109
110class CGameClient : public IGameClient
111{
112public:
113 // all components
114 CInfoMessages m_InfoMessages;
115 CCamera m_Camera;
116 CChat m_Chat;
117 CMotd m_Motd;
118 CBroadcast m_Broadcast;
119 CGameConsole m_GameConsole;
120 CBinds m_Binds;
121 CParticles m_Particles;
122 CMenus m_Menus;
123 CSkins m_Skins;
124 CCountryFlags m_CountryFlags;
125 CFlow m_Flow;
126 CHud m_Hud;
127 CDebugHud m_DebugHud;
128 CControls m_Controls;
129 CEffects m_Effects;
130 CScoreboard m_Scoreboard;
131 CStatboard m_Statboard;
132 CSounds m_Sounds;
133 CEmoticon m_Emoticon;
134 CDamageInd m_DamageInd;
135 CVoting m_Voting;
136 CSpectator m_Spectator;
137
138 CPlayers m_Players;
139 CNamePlates m_NamePlates;
140 CFreezeBars m_FreezeBars;
141 CItems m_Items;
142 CMapImages m_MapImages;
143
144 CMapLayers m_MapLayersBackground = CMapLayers{CMapLayers::TYPE_BACKGROUND};
145 CMapLayers m_MapLayersForeground = CMapLayers{CMapLayers::TYPE_FOREGROUND};
146 CBackground m_Background;
147 CMenuBackground m_MenuBackground;
148
149 CMapSounds m_MapSounds;
150
151 CRaceDemo m_RaceDemo;
152 CGhost m_Ghost;
153
154 CTooltips m_Tooltips;
155
156private:
157 std::vector<class CComponent *> m_vpAll;
158 std::vector<class CComponent *> m_vpInput;
159 CNetObjHandler m_NetObjHandler;
160
161 class IEngine *m_pEngine;
162 class IInput *m_pInput;
163 class IGraphics *m_pGraphics;
164 class ITextRender *m_pTextRender;
165 class IClient *m_pClient;
166 class ISound *m_pSound;
167 class IConfigManager *m_pConfigManager;
168 class CConfig *m_pConfig;
169 class IConsole *m_pConsole;
170 class IStorage *m_pStorage;
171 class IDemoPlayer *m_pDemoPlayer;
172 class IFavorites *m_pFavorites;
173 class IServerBrowser *m_pServerBrowser;
174 class IEditor *m_pEditor;
175 class IFriends *m_pFriends;
176 class IFriends *m_pFoes;
177#if defined(CONF_AUTOUPDATE)
178 class IUpdater *m_pUpdater;
179#endif
180 class IHttp *m_pHttp;
181
182 CLayers m_Layers;
183 CCollision m_Collision;
184 CUi m_UI;
185
186 void ProcessEvents();
187 void UpdatePositions();
188
189 int m_EditorMovementDelay = 5;
190 void UpdateEditorIngameMoved();
191
192 int m_PredictedTick;
193 int m_aLastNewPredictedTick[NUM_DUMMIES];
194
195 int m_LastRoundStartTick;
196
197 int m_LastFlagCarrierRed;
198 int m_LastFlagCarrierBlue;
199
200 int m_aCheckInfo[NUM_DUMMIES];
201
202 char m_aDDNetVersionStr[64];
203
204 static void ConTeam(IConsole::IResult *pResult, void *pUserData);
205 static void ConKill(IConsole::IResult *pResult, void *pUserData);
206
207 static void ConchainLanguageUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
208 static void ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
209 static void ConchainSpecialDummyInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
210 static void ConchainRefreshSkins(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
211 static void ConchainSpecialDummy(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
212 static void ConchainClTextEntitiesSize(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
213
214 static void ConTuneZone(IConsole::IResult *pResult, void *pUserData);
215
216 static void ConchainMenuMap(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
217
218 // only used in OnPredict
219 vec2 m_aLastPos[MAX_CLIENTS];
220 bool m_aLastActive[MAX_CLIENTS];
221
222 // only used in OnNewSnapshot
223 bool m_GameOver = false;
224 bool m_GamePaused = false;
225 int m_PrevLocalId = -1;
226
227public:
228 IKernel *Kernel() { return IInterface::Kernel(); }
229 IEngine *Engine() const { return m_pEngine; }
230 class IGraphics *Graphics() const { return m_pGraphics; }
231 class IClient *Client() const { return m_pClient; }
232 class CUi *Ui() { return &m_UI; }
233 class ISound *Sound() const { return m_pSound; }
234 class IInput *Input() const { return m_pInput; }
235 class IStorage *Storage() const { return m_pStorage; }
236 class IConfigManager *ConfigManager() const { return m_pConfigManager; }
237 class CConfig *Config() const { return m_pConfig; }
238 class IConsole *Console() { return m_pConsole; }
239 class ITextRender *TextRender() const { return m_pTextRender; }
240 class IDemoPlayer *DemoPlayer() const { return m_pDemoPlayer; }
241 class IDemoRecorder *DemoRecorder(int Recorder) const { return Client()->DemoRecorder(Recorder); }
242 class IFavorites *Favorites() const { return m_pFavorites; }
243 class IServerBrowser *ServerBrowser() const { return m_pServerBrowser; }
244 class CRenderTools *RenderTools() { return &m_RenderTools; }
245 class CLayers *Layers() { return &m_Layers; }
246 CCollision *Collision() { return &m_Collision; }
247 class IEditor *Editor() { return m_pEditor; }
248 class IFriends *Friends() { return m_pFriends; }
249 class IFriends *Foes() { return m_pFoes; }
250#if defined(CONF_AUTOUPDATE)
251 class IUpdater *Updater()
252 {
253 return m_pUpdater;
254 }
255#endif
256 class IHttp *Http()
257 {
258 return m_pHttp;
259 }
260
261 int NetobjNumCorrections()
262 {
263 return m_NetObjHandler.NumObjCorrections();
264 }
265 const char *NetobjCorrectedOn() { return m_NetObjHandler.CorrectedObjOn(); }
266
267 bool m_SuppressEvents;
268 bool m_NewTick;
269 bool m_NewPredictedTick;
270 int m_aFlagDropTick[2];
271
272 enum
273 {
274 SERVERMODE_PURE = 0,
275 SERVERMODE_MOD,
276 SERVERMODE_PUREMOD,
277 };
278 int m_ServerMode;
279 CGameInfo m_GameInfo;
280
281 int m_DemoSpecId;
282
283 vec2 m_LocalCharacterPos;
284
285 // predicted players
286 CCharacterCore m_PredictedPrevChar;
287 CCharacterCore m_PredictedChar;
288
289 // snap pointers
290 struct CSnapState
291 {
292 const CNetObj_Character *m_pLocalCharacter;
293 const CNetObj_Character *m_pLocalPrevCharacter;
294 const CNetObj_PlayerInfo *m_pLocalInfo;
295 const CNetObj_SpectatorInfo *m_pSpectatorInfo;
296 const CNetObj_SpectatorInfo *m_pPrevSpectatorInfo;
297 const CNetObj_Flag *m_apFlags[2];
298 const CNetObj_GameInfo *m_pGameInfoObj;
299 const CNetObj_GameData *m_pGameDataObj;
300 int m_GameDataSnapId;
301
302 const CNetObj_PlayerInfo *m_apPlayerInfos[MAX_CLIENTS];
303 const CNetObj_PlayerInfo *m_apInfoByScore[MAX_CLIENTS];
304 const CNetObj_PlayerInfo *m_apInfoByName[MAX_CLIENTS];
305 const CNetObj_PlayerInfo *m_apInfoByDDTeamScore[MAX_CLIENTS];
306 const CNetObj_PlayerInfo *m_apInfoByDDTeamName[MAX_CLIENTS];
307
308 int m_LocalClientId;
309 int m_NumPlayers;
310 int m_aTeamSize[2];
311
312 // spectate data
313 struct CSpectateInfo
314 {
315 bool m_Active;
316 int m_SpectatorId;
317 bool m_UsePosition;
318 vec2 m_Position;
319 } m_SpecInfo;
320
321 //
322 struct CCharacterInfo
323 {
324 bool m_Active;
325
326 // snapshots
327 CNetObj_Character m_Prev;
328 CNetObj_Character m_Cur;
329
330 CNetObj_DDNetCharacter m_ExtendedData;
331 const CNetObj_DDNetCharacter *m_PrevExtendedData;
332 bool m_HasExtendedData;
333 bool m_HasExtendedDisplayInfo;
334
335 // interpolated position
336 vec2 m_Position;
337 };
338
339 CCharacterInfo m_aCharacters[MAX_CLIENTS];
340 };
341
342 CSnapState m_Snap;
343 int m_aLocalTuneZone[NUM_DUMMIES];
344 bool m_aReceivedTuning[NUM_DUMMIES];
345 int m_aExpectingTuningForZone[NUM_DUMMIES];
346 int m_aExpectingTuningSince[NUM_DUMMIES];
347 CTuningParams m_aTuning[NUM_DUMMIES];
348
349 // client data
350 struct CClientData
351 {
352 int m_UseCustomColor;
353 int m_ColorBody;
354 int m_ColorFeet;
355
356 char m_aName[MAX_NAME_LENGTH];
357 char m_aClan[MAX_CLAN_LENGTH];
358 int m_Country;
359 char m_aSkinName[24];
360 int m_SkinColor;
361 int m_Team;
362 int m_Emoticon;
363 float m_EmoticonStartFraction;
364 int m_EmoticonStartTick;
365
366 bool m_Solo;
367 bool m_Jetpack;
368 bool m_CollisionDisabled;
369 bool m_EndlessHook;
370 bool m_EndlessJump;
371 bool m_HammerHitDisabled;
372 bool m_GrenadeHitDisabled;
373 bool m_LaserHitDisabled;
374 bool m_ShotgunHitDisabled;
375 bool m_HookHitDisabled;
376 bool m_Super;
377 bool m_HasTelegunGun;
378 bool m_HasTelegunGrenade;
379 bool m_HasTelegunLaser;
380 int m_FreezeEnd;
381 bool m_DeepFrozen;
382 bool m_LiveFrozen;
383
384 CCharacterCore m_Predicted;
385 CCharacterCore m_PrevPredicted;
386
387 CTeeRenderInfo m_SkinInfo; // this is what the server reports
388 CTeeRenderInfo m_RenderInfo; // this is what we use
389
390 float m_Angle;
391 bool m_Active;
392 bool m_ChatIgnore;
393 bool m_EmoticonIgnore;
394 bool m_Friend;
395 bool m_Foe;
396
397 int m_AuthLevel;
398 bool m_Afk;
399 bool m_Paused;
400 bool m_Spec;
401
402 // Editor allows 256 switches for now.
403 bool m_aSwitchStates[256];
404
405 CNetObj_Character m_Snapped;
406 CNetObj_Character m_Evolved;
407
408 // rendered characters
409 CNetObj_Character m_RenderCur;
410 CNetObj_Character m_RenderPrev;
411 vec2 m_RenderPos;
412 bool m_IsPredicted;
413 bool m_IsPredictedLocal;
414 int64_t m_aSmoothStart[2];
415 int64_t m_aSmoothLen[2];
416 vec2 m_aPredPos[200];
417 int m_aPredTick[200];
418 bool m_SpecCharPresent;
419 vec2 m_SpecChar;
420
421 void UpdateRenderInfo(bool IsTeamPlay);
422 void Reset();
423 };
424
425 CClientData m_aClients[MAX_CLIENTS];
426
427 class CClientStats
428 {
429 int m_IngameTicks;
430 int m_JoinTick;
431 bool m_Active;
432
433 public:
434 CClientStats();
435
436 int m_aFragsWith[NUM_WEAPONS];
437 int m_aDeathsFrom[NUM_WEAPONS];
438 int m_Frags;
439 int m_Deaths;
440 int m_Suicides;
441 int m_BestSpree;
442 int m_CurrentSpree;
443
444 int m_FlagGrabs;
445 int m_FlagCaptures;
446
447 void Reset();
448
449 bool IsActive() const { return m_Active; }
450 void JoinGame(int Tick)
451 {
452 m_Active = true;
453 m_JoinTick = Tick;
454 };
455 void JoinSpec(int Tick)
456 {
457 m_Active = false;
458 m_IngameTicks += Tick - m_JoinTick;
459 };
460 int GetIngameTicks(int Tick) const { return m_IngameTicks + Tick - m_JoinTick; }
461 float GetFPM(int Tick, int TickSpeed) const { return (float)(m_Frags * TickSpeed * 60) / GetIngameTicks(Tick); }
462 };
463
464 CClientStats m_aStats[MAX_CLIENTS];
465
466 CRenderTools m_RenderTools;
467
468 void OnReset();
469
470 size_t ComponentCount() { return m_vpAll.size(); }
471
472 // hooks
473 void OnConnected() override;
474 void OnRender() override;
475 void OnUpdate() override;
476 void OnDummyDisconnect() override;
477 virtual void OnRelease();
478 void OnInit() override;
479 void OnConsoleInit() override;
480 void OnStateChange(int NewState, int OldState) override;
481 void OnMessage(int MsgId, CUnpacker *pUnpacker, int Conn, bool Dummy) override;
482 void InvalidateSnapshot() override;
483 void OnNewSnapshot() override;
484 void OnPredict() override;
485 void OnActivateEditor() override;
486 void OnDummySwap() override;
487 int OnSnapInput(int *pData, bool Dummy, bool Force) override;
488 void OnShutdown() override;
489 void OnEnterGame() override;
490 void OnRconType(bool UsernameReq) override;
491 void OnRconLine(const char *pLine) override;
492 virtual void OnGameOver();
493 virtual void OnStartGame();
494 virtual void OnStartRound();
495 virtual void OnFlagGrab(int TeamId);
496 void OnWindowResize() override;
497
498 bool m_LanguageChanged = false;
499 void OnLanguageChange();
500 void HandleLanguageChanged();
501
502 void RefreshSkins();
503
504 void RenderShutdownMessage() override;
505
506 const char *GetItemName(int Type) const override;
507 const char *Version() const override;
508 const char *NetVersion() const override;
509 int DDNetVersion() const override;
510 const char *DDNetVersionStr() const override;
511
512 // actions
513 // TODO: move these
514 void SendSwitchTeam(int Team);
515 void SendInfo(bool Start);
516 void SendDummyInfo(bool Start) override;
517 void SendKill(int ClientId) const;
518
519 int m_NextChangeInfo;
520
521 // DDRace
522
523 int m_aLocalIds[NUM_DUMMIES];
524 CNetObj_PlayerInput m_DummyInput;
525 CNetObj_PlayerInput m_HammerInput;
526 unsigned int m_DummyFire;
527 bool m_ReceivedDDNetPlayer;
528
529 class CTeamsCore m_Teams;
530
531 int IntersectCharacter(vec2 HookPos, vec2 NewPos, vec2 &NewPos2, int ownId);
532
533 int GetLastRaceTick() const override;
534
535 bool IsTeamPlay() { return m_Snap.m_pGameInfoObj && m_Snap.m_pGameInfoObj->m_GameFlags & GAMEFLAG_TEAMS; }
536
537 bool AntiPingPlayers() { return g_Config.m_ClAntiPing && g_Config.m_ClAntiPingPlayers && !m_Snap.m_SpecInfo.m_Active && Client()->State() != IClient::STATE_DEMOPLAYBACK && (m_aTuning[g_Config.m_ClDummy].m_PlayerCollision || m_aTuning[g_Config.m_ClDummy].m_PlayerHooking); }
538 bool AntiPingGrenade() { return g_Config.m_ClAntiPing && g_Config.m_ClAntiPingGrenade && !m_Snap.m_SpecInfo.m_Active && Client()->State() != IClient::STATE_DEMOPLAYBACK; }
539 bool AntiPingWeapons() { return g_Config.m_ClAntiPing && g_Config.m_ClAntiPingWeapons && !m_Snap.m_SpecInfo.m_Active && Client()->State() != IClient::STATE_DEMOPLAYBACK; }
540 bool AntiPingGunfire() { return AntiPingGrenade() && AntiPingWeapons() && g_Config.m_ClAntiPingGunfire; }
541 bool Predict() const;
542 bool PredictDummy() { return g_Config.m_ClPredictDummy && Client()->DummyConnected() && m_Snap.m_LocalClientId >= 0 && m_PredictedDummyId >= 0 && !m_aClients[m_PredictedDummyId].m_Paused; }
543 const CTuningParams *GetTuning(int i) { return &m_aTuningList[i]; }
544 ColorRGBA GetDDTeamColor(int DDTeam, float Lightness = 0.5f) const;
545
546 CGameWorld m_GameWorld;
547 CGameWorld m_PredictedWorld;
548 CGameWorld m_PrevPredictedWorld;
549
550 std::vector<SSwitchers> &Switchers() { return m_GameWorld.m_Core.m_vSwitchers; }
551 std::vector<SSwitchers> &PredSwitchers() { return m_PredictedWorld.m_Core.m_vSwitchers; }
552
553 void DummyResetInput() override;
554 void Echo(const char *pString) override;
555 bool IsOtherTeam(int ClientId) const;
556 int SwitchStateTeam() const;
557 bool IsLocalCharSuper() const;
558 bool CanDisplayWarning() const override;
559 CNetObjHandler *GetNetObjHandler() override;
560
561 void LoadGameSkin(const char *pPath, bool AsDir = false);
562 void LoadEmoticonsSkin(const char *pPath, bool AsDir = false);
563 void LoadParticlesSkin(const char *pPath, bool AsDir = false);
564 void LoadHudSkin(const char *pPath, bool AsDir = false);
565 void LoadExtrasSkin(const char *pPath, bool AsDir = false);
566
567 struct SClientGameSkin
568 {
569 // health armor hud
570 IGraphics::CTextureHandle m_SpriteHealthFull;
571 IGraphics::CTextureHandle m_SpriteHealthEmpty;
572 IGraphics::CTextureHandle m_SpriteArmorFull;
573 IGraphics::CTextureHandle m_SpriteArmorEmpty;
574
575 // cursors
576 IGraphics::CTextureHandle m_SpriteWeaponHammerCursor;
577 IGraphics::CTextureHandle m_SpriteWeaponGunCursor;
578 IGraphics::CTextureHandle m_SpriteWeaponShotgunCursor;
579 IGraphics::CTextureHandle m_SpriteWeaponGrenadeCursor;
580 IGraphics::CTextureHandle m_SpriteWeaponNinjaCursor;
581 IGraphics::CTextureHandle m_SpriteWeaponLaserCursor;
582
583 IGraphics::CTextureHandle m_aSpriteWeaponCursors[6];
584
585 // weapons and hook
586 IGraphics::CTextureHandle m_SpriteHookChain;
587 IGraphics::CTextureHandle m_SpriteHookHead;
588 IGraphics::CTextureHandle m_SpriteWeaponHammer;
589 IGraphics::CTextureHandle m_SpriteWeaponGun;
590 IGraphics::CTextureHandle m_SpriteWeaponShotgun;
591 IGraphics::CTextureHandle m_SpriteWeaponGrenade;
592 IGraphics::CTextureHandle m_SpriteWeaponNinja;
593 IGraphics::CTextureHandle m_SpriteWeaponLaser;
594
595 IGraphics::CTextureHandle m_aSpriteWeapons[6];
596
597 // particles
598 IGraphics::CTextureHandle m_aSpriteParticles[9];
599
600 // stars
601 IGraphics::CTextureHandle m_aSpriteStars[3];
602
603 // projectiles
604 IGraphics::CTextureHandle m_SpriteWeaponGunProjectile;
605 IGraphics::CTextureHandle m_SpriteWeaponShotgunProjectile;
606 IGraphics::CTextureHandle m_SpriteWeaponGrenadeProjectile;
607 IGraphics::CTextureHandle m_SpriteWeaponHammerProjectile;
608 IGraphics::CTextureHandle m_SpriteWeaponNinjaProjectile;
609 IGraphics::CTextureHandle m_SpriteWeaponLaserProjectile;
610
611 IGraphics::CTextureHandle m_aSpriteWeaponProjectiles[6];
612
613 // muzzles
614 IGraphics::CTextureHandle m_aSpriteWeaponGunMuzzles[3];
615 IGraphics::CTextureHandle m_aSpriteWeaponShotgunMuzzles[3];
616 IGraphics::CTextureHandle m_aaSpriteWeaponNinjaMuzzles[3];
617
618 IGraphics::CTextureHandle m_aaSpriteWeaponsMuzzles[6][3];
619
620 // pickups
621 IGraphics::CTextureHandle m_SpritePickupHealth;
622 IGraphics::CTextureHandle m_SpritePickupArmor;
623 IGraphics::CTextureHandle m_SpritePickupArmorShotgun;
624 IGraphics::CTextureHandle m_SpritePickupArmorGrenade;
625 IGraphics::CTextureHandle m_SpritePickupArmorNinja;
626 IGraphics::CTextureHandle m_SpritePickupArmorLaser;
627 IGraphics::CTextureHandle m_SpritePickupGrenade;
628 IGraphics::CTextureHandle m_SpritePickupShotgun;
629 IGraphics::CTextureHandle m_SpritePickupLaser;
630 IGraphics::CTextureHandle m_SpritePickupNinja;
631 IGraphics::CTextureHandle m_SpritePickupGun;
632 IGraphics::CTextureHandle m_SpritePickupHammer;
633
634 IGraphics::CTextureHandle m_aSpritePickupWeapons[6];
635 IGraphics::CTextureHandle m_aSpritePickupWeaponArmor[4];
636
637 // flags
638 IGraphics::CTextureHandle m_SpriteFlagBlue;
639 IGraphics::CTextureHandle m_SpriteFlagRed;
640
641 // ninja bar (0.7)
642 IGraphics::CTextureHandle m_SpriteNinjaBarFullLeft;
643 IGraphics::CTextureHandle m_SpriteNinjaBarFull;
644 IGraphics::CTextureHandle m_SpriteNinjaBarEmpty;
645 IGraphics::CTextureHandle m_SpriteNinjaBarEmptyRight;
646
647 bool IsSixup()
648 {
649 return m_SpriteNinjaBarFullLeft.IsValid();
650 }
651 };
652
653 SClientGameSkin m_GameSkin;
654 bool m_GameSkinLoaded = false;
655
656 struct SClientParticlesSkin
657 {
658 IGraphics::CTextureHandle m_SpriteParticleSlice;
659 IGraphics::CTextureHandle m_SpriteParticleBall;
660 IGraphics::CTextureHandle m_aSpriteParticleSplat[3];
661 IGraphics::CTextureHandle m_SpriteParticleSmoke;
662 IGraphics::CTextureHandle m_SpriteParticleShell;
663 IGraphics::CTextureHandle m_SpriteParticleExpl;
664 IGraphics::CTextureHandle m_SpriteParticleAirJump;
665 IGraphics::CTextureHandle m_SpriteParticleHit;
666 IGraphics::CTextureHandle m_aSpriteParticles[10];
667 };
668
669 SClientParticlesSkin m_ParticlesSkin;
670 bool m_ParticlesSkinLoaded = false;
671
672 struct SClientEmoticonsSkin
673 {
674 IGraphics::CTextureHandle m_aSpriteEmoticons[16];
675 };
676
677 SClientEmoticonsSkin m_EmoticonsSkin;
678 bool m_EmoticonsSkinLoaded = false;
679
680 struct SClientHudSkin
681 {
682 IGraphics::CTextureHandle m_SpriteHudAirjump;
683 IGraphics::CTextureHandle m_SpriteHudAirjumpEmpty;
684 IGraphics::CTextureHandle m_SpriteHudSolo;
685 IGraphics::CTextureHandle m_SpriteHudCollisionDisabled;
686 IGraphics::CTextureHandle m_SpriteHudEndlessJump;
687 IGraphics::CTextureHandle m_SpriteHudEndlessHook;
688 IGraphics::CTextureHandle m_SpriteHudJetpack;
689 IGraphics::CTextureHandle m_SpriteHudFreezeBarFullLeft;
690 IGraphics::CTextureHandle m_SpriteHudFreezeBarFull;
691 IGraphics::CTextureHandle m_SpriteHudFreezeBarEmpty;
692 IGraphics::CTextureHandle m_SpriteHudFreezeBarEmptyRight;
693 IGraphics::CTextureHandle m_SpriteHudNinjaBarFullLeft;
694 IGraphics::CTextureHandle m_SpriteHudNinjaBarFull;
695 IGraphics::CTextureHandle m_SpriteHudNinjaBarEmpty;
696 IGraphics::CTextureHandle m_SpriteHudNinjaBarEmptyRight;
697 IGraphics::CTextureHandle m_SpriteHudHookHitDisabled;
698 IGraphics::CTextureHandle m_SpriteHudHammerHitDisabled;
699 IGraphics::CTextureHandle m_SpriteHudShotgunHitDisabled;
700 IGraphics::CTextureHandle m_SpriteHudGrenadeHitDisabled;
701 IGraphics::CTextureHandle m_SpriteHudLaserHitDisabled;
702 IGraphics::CTextureHandle m_SpriteHudGunHitDisabled;
703 IGraphics::CTextureHandle m_SpriteHudDeepFrozen;
704 IGraphics::CTextureHandle m_SpriteHudLiveFrozen;
705 IGraphics::CTextureHandle m_SpriteHudTeleportGrenade;
706 IGraphics::CTextureHandle m_SpriteHudTeleportGun;
707 IGraphics::CTextureHandle m_SpriteHudTeleportLaser;
708 IGraphics::CTextureHandle m_SpriteHudPracticeMode;
709 IGraphics::CTextureHandle m_SpriteHudLockMode;
710 IGraphics::CTextureHandle m_SpriteHudTeam0Mode;
711 IGraphics::CTextureHandle m_SpriteHudDummyHammer;
712 IGraphics::CTextureHandle m_SpriteHudDummyCopy;
713 };
714
715 SClientHudSkin m_HudSkin;
716 bool m_HudSkinLoaded = false;
717
718 struct SClientExtrasSkin
719 {
720 IGraphics::CTextureHandle m_SpriteParticleSnowflake;
721 IGraphics::CTextureHandle m_aSpriteParticles[1];
722 };
723
724 SClientExtrasSkin m_ExtrasSkin;
725 bool m_ExtrasSkinLoaded = false;
726
727 const std::vector<CSnapEntities> &SnapEntities() { return m_vSnapEntities; }
728
729 int m_MultiViewTeam;
730 int m_MultiViewPersonalZoom;
731 bool m_MultiViewShowHud;
732 bool m_MultiViewActivated;
733 bool m_aMultiViewId[MAX_CLIENTS];
734
735 void ResetMultiView();
736 int FindFirstMultiViewId();
737 void CleanMultiViewId(int ClientId);
738
739private:
740 std::vector<CSnapEntities> m_vSnapEntities;
741 void SnapCollectEntities();
742
743 bool m_aDDRaceMsgSent[NUM_DUMMIES];
744 int m_aShowOthers[NUM_DUMMIES];
745
746 void UpdatePrediction();
747 void UpdateRenderedCharacters();
748
749 int m_aLastUpdateTick[MAX_CLIENTS] = {0};
750 void DetectStrongHook();
751
752 vec2 GetSmoothPos(int ClientId);
753
754 int m_PredictedDummyId;
755 int m_IsDummySwapping;
756 CCharOrder m_CharOrder;
757 int m_aSwitchStateTeam[NUM_DUMMIES];
758
759 enum
760 {
761 NUM_TUNEZONES = 256
762 };
763 void LoadMapSettings();
764 CTuningParams m_aTuningList[NUM_TUNEZONES];
765 CTuningParams *TuningList() { return m_aTuningList; }
766
767 float m_LastZoom;
768 float m_LastScreenAspect;
769 bool m_LastDummyConnected;
770
771 void HandleMultiView();
772 bool IsMultiViewIdSet();
773 void CleanMultiViewIds();
774 bool InitMultiView(int Team);
775 float CalculateMultiViewMultiplier(vec2 TargetPos);
776 float CalculateMultiViewZoom(vec2 MinPos, vec2 MaxPos, float Vel);
777 float MapValue(float MaxValue, float MinValue, float MaxRange, float MinRange, float Value);
778
779 struct SMultiView
780 {
781 bool m_Solo;
782 bool m_IsInit;
783 bool m_Teleported;
784 bool m_aVanish[MAX_CLIENTS];
785 vec2 m_OldPos;
786 int m_OldPersonalZoom;
787 float m_SecondChance;
788 float m_OldCameraDistance;
789 float m_aLastFreeze[MAX_CLIENTS];
790 };
791
792 SMultiView m_MultiView;
793};
794
795ColorRGBA CalculateNameColor(ColorHSLA TextColorHSL);
796
797#endif
798