ddnet/src/game/client/components/ghost.h
def 8908102536 Add cl_confirm_disconnect_quit_time (fixes #1530)
Number of minutes of active racing time before being asked to confirm
disconnecting, disconnecting dummy or quitting through GUI. Defaults to
20 minutes, -1 to disable, 0 to always enable.

Also removed confirmation to quit when in main menu, except when having
an unsaved map in editor.

Spectate and kill should already be safe thanks to server-side kill
protection.
2019-03-25 20:10:38 +01:00

173 lines
3.5 KiB
C++

/* (c) Rajh, Redix and Sushi. */
#ifndef GAME_CLIENT_COMPONENTS_GHOST_H
#define GAME_CLIENT_COMPONENTS_GHOST_H
#include <game/client/component.h>
enum
{
GHOSTDATA_TYPE_SKIN = 0,
GHOSTDATA_TYPE_CHARACTER_NO_TICK,
GHOSTDATA_TYPE_CHARACTER,
GHOSTDATA_TYPE_START_TICK
};
struct CGhostSkin
{
int m_Skin0;
int m_Skin1;
int m_Skin2;
int m_Skin3;
int m_Skin4;
int m_Skin5;
int m_UseCustomColor;
int m_ColorBody;
int m_ColorFeet;
};
struct CGhostCharacter_NoTick
{
int m_X;
int m_Y;
int m_VelX;
int m_VelY;
int m_Angle;
int m_Direction;
int m_Weapon;
int m_HookState;
int m_HookX;
int m_HookY;
int m_AttackTick;
};
struct CGhostCharacter : public CGhostCharacter_NoTick
{
int m_Tick;
};
class CGhost : public CComponent
{
private:
enum
{
MAX_ACTIVE_GHOSTS = 8,
};
class CGhostPath
{
int m_ChunkSize;
int m_NumItems;
std::vector<CGhostCharacter*> m_lChunks;
public:
CGhostPath() { Reset(); }
~CGhostPath() { Reset(); }
CGhostPath(const CGhostPath &Other) = delete;
CGhostPath &operator = (const CGhostPath &Other) = delete;
CGhostPath(CGhostPath &&Other);
CGhostPath &operator = (CGhostPath &&Other);
void Reset(int ChunkSize = 25 * 60); // one minute with default snap rate
void SetSize(int Items);
int Size() const { return m_NumItems; }
void Add(CGhostCharacter Char);
CGhostCharacter *Get(int Index);
};
class CGhostItem
{
public:
CTeeRenderInfo m_RenderInfo;
CGhostSkin m_Skin;
CGhostPath m_Path;
int m_StartTick;
char m_aPlayer[MAX_NAME_LENGTH];
int m_PlaybackPos;
CGhostItem() { Reset(); }
bool Empty() const { return m_Path.Size() == 0; }
void Reset()
{
m_Path.Reset();
m_StartTick = -1;
m_PlaybackPos = -1;
}
};
static const char *ms_pGhostDir;
class IGhostLoader *m_pGhostLoader;
class IGhostRecorder *m_pGhostRecorder;
CGhostItem m_aActiveGhosts[MAX_ACTIVE_GHOSTS];
CGhostItem m_CurGhost;
char m_aTmpFilename[128];
int m_NewRenderTick;
int m_StartRenderTick;
int m_LastDeathTick;
int m_LastRaceTick;
bool m_Recording;
bool m_Rendering;
bool m_RenderingStartedByServer;
static void GetGhostSkin(CGhostSkin *pSkin, const char *pSkinName, int UseCustomColor, int ColorBody, int ColorFeet);
static void GetGhostCharacter(CGhostCharacter *pGhostChar, const CNetObj_Character *pChar);
static void GetNetObjCharacter(CNetObj_Character *pChar, const CGhostCharacter *pGhostChar);
void GetPath(char *pBuf, int Size, const char *pPlayerName, int Time = -1) const;
void AddInfos(const CNetObj_Character *pChar);
int GetSlot() const;
void CheckStart();
void CheckStartLocal(bool Predicted);
void TryRenderStart(int Tick, bool ServerControl);
void StartRecord(int Tick);
void StopRecord(int Time = -1);
void StartRender(int Tick);
void StopRender();
void InitRenderInfos(CGhostItem *pGhost);
static void ConGPlay(IConsole::IResult *pResult, void *pUserData);
public:
bool m_AllowRestart;
CGhost();
virtual void OnRender();
virtual void OnConsoleInit();
virtual void OnReset();
virtual void OnMessage(int MsgType, void *pRawMsg);
virtual void OnMapLoad();
void OnNewSnapshot();
void OnNewPredictedSnapshot();
int FreeSlots() const;
int Load(const char *pFilename);
void Unload(int Slot);
void UnloadAll();
void SaveGhost(CMenus::CGhostItem *pItem);
const char *GetGhostDir() const { return ms_pGhostDir; }
class IGhostLoader *GhostLoader() const { return m_pGhostLoader; }
class IGhostRecorder *GhostRecorder() const { return m_pGhostRecorder; }
int GetLastRaceTick();
};
#endif