2424:  Keep hook when loading  r=heinrich5991 a=Zwelf

Solves issue discussed in #2374. Also keeps direction and jump, which is evaluated when player is in /pause. Fire could be deleted, as it does not affect game play in any way.

Co-authored-by: Zwelf <zwelf@strct.cc>
This commit is contained in:
bors[bot] 2020-07-01 16:01:25 +00:00 committed by GitHub
commit 98779776e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 127 additions and 53 deletions

View file

@ -93,6 +93,15 @@ void CSaveTee::save(CCharacter *pChr)
m_HookTick = pChr->m_Core.m_HookTick;
m_HookState = pChr->m_Core.m_HookState;
m_HookedPlayer = pChr->m_Core.m_HookedPlayer;
m_NewHook = pChr->m_Core.m_NewHook != 0;
m_InputDirection = pChr->m_SavedInput.m_Direction;
m_InputJump = pChr->m_SavedInput.m_Jump;
m_InputFire = pChr->m_SavedInput.m_Fire;
m_InputHook = pChr->m_SavedInput.m_Hook;
m_ReloadTimer = pChr->m_ReloadTimer;
FormatUuid(pChr->GameServer()->GameUuid(), m_aGameUuid, sizeof(m_aGameUuid));
}
@ -171,15 +180,23 @@ void CSaveTee::load(CCharacter *pChr, int Team)
pChr->m_Core.m_HookTick = m_HookTick;
if(m_HookState == HOOK_GRABBED)
pChr->m_Core.m_HookState = m_HookState;
if(m_HookedPlayer != -1 && pChr->Teams()->m_Core.Team(m_HookedPlayer) != Team)
{
pChr->m_Core.m_HookState = HOOK_FLYING;
pChr->m_Core.m_HookedPlayer = -1;
pChr->m_Core.m_HookState = HOOK_FLYING;
}
else
{
pChr->m_Core.m_HookState = m_HookState;
pChr->m_Core.m_HookedPlayer = m_HookedPlayer;
}
pChr->m_Core.m_NewHook = m_NewHook;
pChr->m_SavedInput.m_Direction = m_InputDirection;
pChr->m_SavedInput.m_Jump = m_InputJump;
pChr->m_SavedInput.m_Fire = m_InputFire;
pChr->m_SavedInput.m_Hook = m_InputHook;
pChr->m_ReloadTimer = m_ReloadTimer;
pChr->SetSolo(m_IsSolo);
@ -188,11 +205,24 @@ void CSaveTee::load(CCharacter *pChr, int Team)
pChr->SetRescue();
}
char* CSaveTee::GetString()
char* CSaveTee::GetString(const CSaveTeam *pTeam)
{
// Add time penalty of 60 seconds (only to the database)
int Time = m_Time + 60 * SERVER_TICK_SPEED;
int HookedPlayer = -1;
if(m_HookedPlayer != -1)
{
for(int n = 0; n < pTeam->GetMembersCount(); n++)
{
if(m_HookedPlayer == pTeam->m_pSavedTees[n].GetClientID())
{
HookedPlayer = n;
break;
}
}
}
str_format(m_aString, sizeof(m_aString),
"%s\t%d\t%d\t%d\t%d\t%d\t"
// weapons
@ -221,7 +251,10 @@ char* CSaveTee::GetString()
"%f\t%f\t%f\t%f\t%f\t"
"%d\t"
"%d\t%d\t%d\t"
"%s",
"%s\t"
"%d\t%d\t"
"%d\t%d\t%d\t%d\t"
"%d",
m_aName, m_Alive, m_Paused, m_NeededFaketuning, m_TeeFinished, m_IsSolo,
// weapons
m_aWeapons[0].m_AmmoRegenStart, m_aWeapons[0].m_Ammo, m_aWeapons[0].m_Ammocost, m_aWeapons[0].m_Got,
@ -249,7 +282,10 @@ char* CSaveTee::GetString()
m_aCpCurrent[20], m_aCpCurrent[21], m_aCpCurrent[22], m_aCpCurrent[23], m_aCpCurrent[24],
m_NotEligibleForFinish,
m_HasTelegunGun, m_HasTelegunLaser, m_HasTelegunGrenade,
m_aGameUuid
m_aGameUuid,
HookedPlayer, m_NewHook,
m_InputDirection, m_InputJump, m_InputFire, m_InputHook,
m_ReloadTimer
);
return m_aString;
}
@ -285,7 +321,10 @@ int CSaveTee::LoadString(const char* String)
"%f\t%f\t%f\t%f\t%f\t"
"%d\t"
"%d\t%d\t%d\t"
"%*s", // discard the game uuid
"%*s\t" // discard the game uuid
"%d\t%d"
"%d\t%d\t%d\t%d\t"
"%d",
m_aName, &m_Alive, &m_Paused, &m_NeededFaketuning, &m_TeeFinished, &m_IsSolo,
// weapons
&m_aWeapons[0].m_AmmoRegenStart, &m_aWeapons[0].m_Ammo, &m_aWeapons[0].m_Ammocost, &m_aWeapons[0].m_Got,
@ -312,7 +351,10 @@ int CSaveTee::LoadString(const char* String)
&m_aCpCurrent[15], &m_aCpCurrent[16], &m_aCpCurrent[17], &m_aCpCurrent[18], &m_aCpCurrent[19],
&m_aCpCurrent[20], &m_aCpCurrent[21], &m_aCpCurrent[22], &m_aCpCurrent[23], &m_aCpCurrent[24],
&m_NotEligibleForFinish,
&m_HasTelegunGun, &m_HasTelegunLaser, &m_HasTelegunGrenade
&m_HasTelegunGun, &m_HasTelegunLaser, &m_HasTelegunGrenade,
&m_HookedPlayer, &m_NewHook,
&m_InputDirection, &m_InputJump, &m_InputFire, &m_InputHook,
&m_ReloadTimer
);
switch(Num) // Don't forget to update this when you save / load more / less.
{
@ -325,6 +367,17 @@ int CSaveTee::LoadString(const char* String)
m_HasTelegunGun = 0;
// fall through
case 100:
m_HookedPlayer = -1;
m_NewHook = false;
if(m_HookState == HOOK_GRABBED)
m_HookState = HOOK_FLYING;
m_InputDirection = 0;
m_InputJump = 0;
m_InputFire = 0;
m_InputHook = 0;
m_ReloadTimer = 0;
// fall through
case 107:
return 0;
default:
dbg_msg("load", "failed to load tee-string");
@ -333,6 +386,13 @@ int CSaveTee::LoadString(const char* String)
}
}
void CSaveTee::LoadHookedPlayer(const CSaveTeam *pTeam)
{
if(m_HookedPlayer == -1)
return;
m_HookedPlayer = pTeam->m_pSavedTees[m_HookedPlayer].GetClientID();
}
CSaveTeam::CSaveTeam(IGameController* Controller)
{
m_pController = Controller;
@ -373,17 +433,18 @@ int CSaveTeam::save(int Team)
m_pSavedTees = new CSaveTee[m_MembersCount];
int j = 0;
for (int i = 0; i < MAX_CLIENTS; i++)
CCharacter *p = (CCharacter *)m_pController->GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER);
for(; p; p = (CCharacter *)p->TypeNext())
{
if(Teams->m_Core.Team(i) == Team)
{
if(m_pController->GameServer()->m_apPlayers[i] && m_pController->GameServer()->m_apPlayers[i]->GetCharacter())
m_pSavedTees[j].save(m_pController->GameServer()->m_apPlayers[i]->GetCharacter());
else
return 3;
j++;
}
if(m_MembersCount == j)
return 3;
if(Teams->m_Core.Team(p->GetPlayer()->GetCID()) != Team)
continue;
m_pSavedTees[j].save(p);
j++;
}
if(m_MembersCount != j)
return 3;
if(m_pController->GameServer()->Collision()->m_NumSwitchers)
{
@ -439,7 +500,7 @@ void CSaveTeam::load(int Team)
if(m_Practice)
pTeams->EnablePractice(Team);
for (int i = 0; i < m_MembersCount; i++)
for (int i = m_MembersCount; i-- > 0;)
{
int ClientID = m_pSavedTees[i].GetClientID();
if(m_pController->GameServer()->m_apPlayers[ClientID] && pTeams->m_Core.Team(ClientID) == Team)
@ -463,10 +524,8 @@ void CSaveTeam::load(int Team)
CCharacter* CSaveTeam::MatchCharacter(int ClientID, int SaveID)
{
if(m_pController->GameServer()->m_apPlayers[ClientID]->GetCharacter())
return m_pController->GameServer()->m_apPlayers[ClientID]->GetCharacter();
else
return m_pController->GameServer()->m_apPlayers[ClientID]->ForceSpawn(m_pSavedTees[SaveID].GetPos());
m_pController->GameServer()->m_apPlayers[ClientID]->KillCharacter(WEAPON_GAME);
return m_pController->GameServer()->m_apPlayers[ClientID]->ForceSpawn(m_pSavedTees[SaveID].GetPos());
}
char* CSaveTeam::GetString()
@ -476,7 +535,7 @@ char* CSaveTeam::GetString()
for(int i = 0; i < m_MembersCount; i++)
{
char aBuf[1024];
str_format(aBuf, sizeof(aBuf), "\n%s", m_pSavedTees[i].GetString());
str_format(aBuf, sizeof(aBuf), "\n%s", m_pSavedTees[i].GetString(this));
str_append(m_aString, aBuf, sizeof(m_aString));
}
@ -602,40 +661,40 @@ int CSaveTeam::LoadString(const char* String)
m_pSwitchers = new SSimpleSwitchers[m_NumSwitchers+1];
for (int n = 1; n < m_NumSwitchers+1; n++)
{
while (m_aString[Pos] != '\n' && Pos < sizeof(m_aString) && m_aString[Pos]) // find next \n or \0
Pos++;
CopyPos = m_aString + LastPos;
StrSize = Pos - LastPos + 1;
if(m_aString[Pos] == '\n')
{
while (m_aString[Pos] != '\n' && Pos < sizeof(m_aString) && m_aString[Pos]) // find next \n or \0
Pos++;
Pos++; // skip \n
LastPos = Pos;
}
CopyPos = m_aString + LastPos;
StrSize = Pos - LastPos + 1;
if(m_aString[Pos] == '\n')
{
Pos++; // skip \n
LastPos = Pos;
}
if(StrSize <= 0)
{
dbg_msg("load", "savegame: wrong format (couldn't load switcher)");
return 1;
}
if(StrSize <= 0)
if(StrSize < sizeof(Switcher))
{
str_copy(Switcher, CopyPos, StrSize);
int Num = sscanf(Switcher, "%d\t%d\t%d", &(m_pSwitchers[n].m_Status), &(m_pSwitchers[n].m_EndTime), &(m_pSwitchers[n].m_Type));
if(Num != 3)
{
dbg_msg("load", "savegame: wrong format (couldn't load switcher)");
return 1;
}
if(StrSize < sizeof(Switcher))
{
str_copy(Switcher, CopyPos, StrSize);
int Num = sscanf(Switcher, "%d\t%d\t%d", &(m_pSwitchers[n].m_Status), &(m_pSwitchers[n].m_EndTime), &(m_pSwitchers[n].m_Type));
if(Num != 3)
{
dbg_msg("load", "failed to load switcher");
dbg_msg("load", "loaded %d vars", Num-1);
}
}
else
{
dbg_msg("load", "savegame: wrong format (couldn't load switcher, too big)");
return 1;
dbg_msg("load", "failed to load switcher");
dbg_msg("load", "loaded %d vars", Num-1);
}
}
else
{
dbg_msg("load", "savegame: wrong format (couldn't load switcher, too big)");
return 1;
}
}
return 0;
}
@ -674,6 +733,7 @@ bool CSaveTeam::MatchPlayers(const char (*paNames)[MAX_NAME_LENGTH], const int *
{
m_pSavedTees[i].SetClientID(pClientID[j]);
Found = true;
break;
}
}
if(!Found)
@ -682,5 +742,8 @@ bool CSaveTeam::MatchPlayers(const char (*paNames)[MAX_NAME_LENGTH], const int *
return false;
}
}
// match hook to correct ClientID
for (int n = 0; n < m_MembersCount; n++)
m_pSavedTees[n].LoadHookedPlayer(this);
return true;
}

View file

@ -8,6 +8,7 @@
class IGameController;
class CGameContext;
class CCharacter;
class CSaveTeam;
class CSaveTee
{
@ -16,8 +17,9 @@ public:
~CSaveTee();
void save(CCharacter* pchr);
void load(CCharacter* pchr, int Team);
char* GetString();
char* GetString(const CSaveTeam *pTeam);
int LoadString(const char* String);
void LoadHookedPlayer(const CSaveTeam *pTeam);
vec2 GetPos() const { return m_Pos; }
const char* GetName() const { return m_aName; }
int GetClientID() const { return m_ClientID; }
@ -43,7 +45,6 @@ private:
int m_Ammo;
int m_Ammocost;
int m_Got;
} m_aWeapons[NUM_WEAPONS];
int m_LastWeapon;
@ -92,6 +93,16 @@ private:
vec2 m_HookTeleBase;
int m_HookTick;
int m_HookState;
int m_HookedPlayer;
int m_NewHook;
// player input
int m_InputDirection;
int m_InputJump;
int m_InputFire;
int m_InputHook;
int m_ReloadTimer;
char m_aGameUuid[UUID_MAXSTRSIZE];
};