mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Improved ghost start accuracy
This commit is contained in:
parent
ac234ad3ee
commit
4c8c546c35
|
@ -71,6 +71,7 @@ void CGhost::AddInfos(const CNetObj_Character *pChar)
|
|||
{
|
||||
Client()->GhostRecorder_Start(m_CurGhost.m_aPlayer);
|
||||
|
||||
GhostRecorder()->WriteData(GHOSTDATA_TYPE_START_TICK, (const char*)&m_CurGhost.m_StartTick, sizeof(int));
|
||||
GhostRecorder()->WriteData(GHOSTDATA_TYPE_SKIN, (const char*)&m_CurGhost.m_Skin, sizeof(CGhostSkin));
|
||||
for(int i = 0; i < NumTicks; i++)
|
||||
GhostRecorder()->WriteData(GHOSTDATA_TYPE_CHARACTER, (const char*)&m_CurGhost.m_lPath[i], sizeof(CGhostCharacter));
|
||||
|
@ -115,21 +116,37 @@ void CGhost::OnRender()
|
|||
vec2 PrevPos = m_pClient->m_PredictedPrevChar.m_Pos;
|
||||
vec2 Pos = m_pClient->m_PredictedChar.m_Pos;
|
||||
if((!m_Rendering || !m_IsSolo) && CRaceHelper::IsStart(m_pClient, PrevPos, Pos))
|
||||
StartRender();
|
||||
StartRender(Client()->PredGameTick());
|
||||
}
|
||||
|
||||
if(m_pClient->m_NewTick)
|
||||
{
|
||||
int PrevTick = m_pClient->m_Snap.m_pLocalPrevCharacter->m_Tick;
|
||||
int CurTick = m_pClient->m_Snap.m_pLocalCharacter->m_Tick;
|
||||
vec2 PrevPos = vec2(m_pClient->m_Snap.m_pLocalPrevCharacter->m_X, m_pClient->m_Snap.m_pLocalPrevCharacter->m_Y);
|
||||
vec2 Pos = vec2(m_pClient->m_Snap.m_pLocalCharacter->m_X, m_pClient->m_Snap.m_pLocalCharacter->m_Y);
|
||||
|
||||
// detecting death, needed because race allows immediate respawning
|
||||
if((!m_Recording || !m_IsSolo) && CRaceHelper::IsStart(m_pClient, PrevPos, Pos) && m_LastDeathTick < PrevTick)
|
||||
if((!m_Recording || !m_IsSolo) && m_LastDeathTick < PrevTick)
|
||||
{
|
||||
if(m_Recording)
|
||||
GhostRecorder()->Stop(0, -1);
|
||||
StartRecord();
|
||||
// estimate the exact start tick
|
||||
int RecordTick = -1;
|
||||
int TickDiff = CurTick - PrevTick;
|
||||
for(int i = 0; i < TickDiff; i++)
|
||||
{
|
||||
if(CRaceHelper::IsStart(m_pClient, mix(PrevPos, Pos, (float)i/TickDiff), mix(PrevPos, Pos, (float)(i+1)/TickDiff)))
|
||||
{
|
||||
RecordTick = PrevTick + i + 1;
|
||||
if(m_IsSolo)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(RecordTick != -1)
|
||||
{
|
||||
if(m_Recording)
|
||||
GhostRecorder()->Stop(0, -1);
|
||||
StartRecord(RecordTick);
|
||||
}
|
||||
}
|
||||
|
||||
if(m_Recording)
|
||||
|
@ -151,7 +168,7 @@ void CGhost::OnRender()
|
|||
continue;
|
||||
|
||||
bool End = false;
|
||||
int GhostTick = pGhost->m_lPath[0].m_Tick + PlaybackTick;
|
||||
int GhostTick = pGhost->m_StartTick + PlaybackTick;
|
||||
while(pGhost->m_lPath[pGhost->m_PlaybackPos].m_Tick < GhostTick && !End)
|
||||
{
|
||||
if(pGhost->m_PlaybackPos < pGhost->m_lPath.size() - 1)
|
||||
|
@ -167,6 +184,9 @@ void CGhost::OnRender()
|
|||
|
||||
int CurPos = pGhost->m_PlaybackPos;
|
||||
int PrevPos = max(0, CurPos - 1);
|
||||
if(pGhost->m_lPath[PrevPos].m_Tick > GhostTick)
|
||||
continue;
|
||||
|
||||
CNetObj_Character Player, Prev;
|
||||
GetNetObjCharacter(&Player, &pGhost->m_lPath[CurPos]);
|
||||
GetNetObjCharacter(&Prev, &pGhost->m_lPath[PrevPos]);
|
||||
|
@ -218,10 +238,11 @@ void CGhost::InitRenderInfos(CGhostItem *pGhost)
|
|||
pRenderInfo->m_Size = 64;
|
||||
}
|
||||
|
||||
void CGhost::StartRecord()
|
||||
void CGhost::StartRecord(int Tick)
|
||||
{
|
||||
m_Recording = true;
|
||||
m_CurGhost.Reset();
|
||||
m_CurGhost.m_StartTick = Tick;
|
||||
|
||||
const CGameClient::CClientData *pData = &m_pClient->m_aClients[m_pClient->m_Snap.m_LocalClientID];
|
||||
str_copy(m_CurGhost.m_aPlayer, g_Config.m_PlayerName, sizeof(m_CurGhost.m_aPlayer));
|
||||
|
@ -251,20 +272,17 @@ void CGhost::StopRecord(int Time)
|
|||
if(Slot != -1)
|
||||
m_aActiveGhosts[Slot] = m_CurGhost;
|
||||
|
||||
char aFilename[128] = { 0 };
|
||||
if(RecordingToFile)
|
||||
Client()->Ghost_GetPath(aFilename, sizeof(aFilename), m_CurGhost.m_aPlayer, Time);
|
||||
|
||||
// create ghost item
|
||||
CMenus::CGhostItem Item;
|
||||
str_copy(Item.m_aFilename, aFilename, sizeof(Item.m_aFilename));
|
||||
if(RecordingToFile)
|
||||
Client()->Ghost_GetPath(Item.m_aFilename, sizeof(Item.m_aFilename), m_CurGhost.m_aPlayer, Time);
|
||||
str_copy(Item.m_aPlayer, m_CurGhost.m_aPlayer, sizeof(Item.m_aPlayer));
|
||||
Item.m_Time = Time;
|
||||
Item.m_Slot = Slot;
|
||||
|
||||
// save new ghost file
|
||||
if(Item.HasFile())
|
||||
Storage()->RenameFile(aTmpFilename, aFilename, IStorage::TYPE_SAVE);
|
||||
Storage()->RenameFile(aTmpFilename, Item.m_aFilename, IStorage::TYPE_SAVE);
|
||||
|
||||
// add item to menu list
|
||||
m_pClient->m_pMenus->UpdateOwnGhost(Item);
|
||||
|
@ -275,10 +293,10 @@ void CGhost::StopRecord(int Time)
|
|||
m_CurGhost.Reset();
|
||||
}
|
||||
|
||||
void CGhost::StartRender()
|
||||
void CGhost::StartRender(int Tick)
|
||||
{
|
||||
m_Rendering = true;
|
||||
m_StartRenderTick = Client()->PredGameTick();
|
||||
m_StartRenderTick = Tick;
|
||||
for(int i = 0; i < MAX_ACTIVE_GHOSTS; i++)
|
||||
m_aActiveGhosts[i].m_PlaybackPos = 0;
|
||||
}
|
||||
|
@ -317,6 +335,7 @@ int CGhost::Load(const char *pFilename)
|
|||
bool FoundSkin = false;
|
||||
bool NoTick = false;
|
||||
bool Error = false;
|
||||
pGhost->m_StartTick = -1;
|
||||
|
||||
int Type;
|
||||
while(!Error && GhostLoader()->ReadNextType(&Type))
|
||||
|
@ -344,6 +363,11 @@ int CGhost::Load(const char *pFilename)
|
|||
if(!GhostLoader()->ReadData(Type, (char*)&pGhost->m_lPath[Index++], sizeof(CGhostCharacter)))
|
||||
Error = true;
|
||||
}
|
||||
else if(Type == GHOSTDATA_TYPE_START_TICK)
|
||||
{
|
||||
if(!GhostLoader()->ReadData(Type, (char*)&pGhost->m_StartTick, sizeof(int)))
|
||||
Error = true;
|
||||
}
|
||||
}
|
||||
|
||||
GhostLoader()->Close();
|
||||
|
@ -364,6 +388,9 @@ int CGhost::Load(const char *pFilename)
|
|||
pGhost->m_lPath[i].m_Tick = StartTick + i;
|
||||
}
|
||||
|
||||
if(pGhost->m_StartTick == -1)
|
||||
pGhost->m_StartTick = pGhost->m_lPath[0].m_Tick;
|
||||
|
||||
if(!FoundSkin)
|
||||
GetGhostSkin(&pGhost->m_Skin, "default", 0, 0, 0);
|
||||
InitRenderInfos(pGhost);
|
||||
|
@ -388,12 +415,15 @@ void CGhost::SaveGhost(CMenus::CGhostItem *pItem)
|
|||
if(!pItem->Active() || pItem->HasFile() || m_aActiveGhosts[Slot].Empty() || GhostRecorder()->IsRecording())
|
||||
return;
|
||||
|
||||
int NumTicks = m_aActiveGhosts[Slot].m_lPath.size();
|
||||
const CGhostItem *pGhost = &m_aActiveGhosts[Slot];
|
||||
|
||||
int NumTicks = pGhost->m_lPath.size();
|
||||
Client()->GhostRecorder_Start(pItem->m_aPlayer, pItem->m_Time);
|
||||
|
||||
GhostRecorder()->WriteData(GHOSTDATA_TYPE_SKIN, (const char*)&m_aActiveGhosts[Slot].m_Skin, sizeof(CGhostSkin));
|
||||
GhostRecorder()->WriteData(GHOSTDATA_TYPE_START_TICK, (const char*)&pGhost->m_StartTick, sizeof(int));
|
||||
GhostRecorder()->WriteData(GHOSTDATA_TYPE_SKIN, (const char*)&pGhost->m_Skin, sizeof(CGhostSkin));
|
||||
for(int i = 0; i < NumTicks; i++)
|
||||
GhostRecorder()->WriteData(GHOSTDATA_TYPE_CHARACTER, (const char*)&m_aActiveGhosts[Slot].m_lPath[i], sizeof(CGhostCharacter));
|
||||
GhostRecorder()->WriteData(GHOSTDATA_TYPE_CHARACTER, (const char*)&pGhost->m_lPath[i], sizeof(CGhostCharacter));
|
||||
|
||||
GhostRecorder()->Stop(NumTicks, pItem->m_Time);
|
||||
Client()->Ghost_GetPath(pItem->m_aFilename, sizeof(pItem->m_aFilename), pItem->m_aPlayer, pItem->m_Time);
|
||||
|
@ -401,7 +431,8 @@ void CGhost::SaveGhost(CMenus::CGhostItem *pItem)
|
|||
|
||||
void CGhost::ConGPlay(IConsole::IResult *pResult, void *pUserData)
|
||||
{
|
||||
((CGhost *)pUserData)->StartRender();
|
||||
CGhost *pGhost = (CGhost *)pUserData;
|
||||
pGhost->StartRender(pGhost->Client()->PredGameTick());
|
||||
}
|
||||
|
||||
void CGhost::OnConsoleInit()
|
||||
|
|
|
@ -9,7 +9,8 @@ enum
|
|||
{
|
||||
GHOSTDATA_TYPE_SKIN = 0,
|
||||
GHOSTDATA_TYPE_CHARACTER_NO_TICK,
|
||||
GHOSTDATA_TYPE_CHARACTER
|
||||
GHOSTDATA_TYPE_CHARACTER,
|
||||
GHOSTDATA_TYPE_START_TICK
|
||||
};
|
||||
|
||||
struct CGhostSkin
|
||||
|
@ -59,6 +60,7 @@ private:
|
|||
CTeeRenderInfo m_RenderInfo;
|
||||
CGhostSkin m_Skin;
|
||||
array<CGhostCharacter> m_lPath;
|
||||
int m_StartTick;
|
||||
char m_aPlayer[MAX_NAME_LENGTH];
|
||||
int m_PlaybackPos;
|
||||
|
||||
|
@ -90,9 +92,9 @@ private:
|
|||
void AddInfos(const CNetObj_Character *pChar);
|
||||
int GetSlot() const;
|
||||
|
||||
void StartRecord();
|
||||
void StartRecord(int Tick);
|
||||
void StopRecord(int Time = -1);
|
||||
void StartRender();
|
||||
void StartRender(int Tick);
|
||||
void StopRender();
|
||||
|
||||
void InitRenderInfos(CGhostItem *pGhost);
|
||||
|
|
|
@ -339,7 +339,7 @@ public:
|
|||
int m_Slot;
|
||||
bool m_Own;
|
||||
|
||||
CGhostItem() : m_Slot(-1), m_Own(false) { }
|
||||
CGhostItem() : m_Slot(-1), m_Own(false) { m_aFilename[0] = 0; }
|
||||
|
||||
bool operator<(const CGhostItem &Other) { return m_Time < Other.m_Time; }
|
||||
|
||||
|
|
Loading…
Reference in a new issue