Fix (partially) skipping through teles and death tiles

Previously you could partially skip through teleporters: Line two
teleporters up in a line, if you through both of them in a single tick,
first, the game would teleport you to the first teleporter's target and
then teleport you to the second teleporter's target. This is fixed by
stopping to process game tiles after a teleport.

You were also able to completely skip through death tiles when moving at
high speed.

Fixes #2056.
This commit is contained in:
heinrich5991 2023-01-30 13:22:37 +01:00
parent d11048ad36
commit 62e9b57408
3 changed files with 28 additions and 8 deletions

View file

@ -809,9 +809,9 @@ bool CCollision::TileExists(int Index) const
if(Index < 0) if(Index < 0)
return false; return false;
if((m_pTiles[Index].m_Index >= TILE_FREEZE && m_pTiles[Index].m_Index <= TILE_TELE_LASER_DISABLE) || (m_pTiles[Index].m_Index >= TILE_LFREEZE && m_pTiles[Index].m_Index <= TILE_LUNFREEZE)) if(m_pTiles[Index].m_Index == TILE_DEATH || (m_pTiles[Index].m_Index >= TILE_FREEZE && m_pTiles[Index].m_Index <= TILE_TELE_LASER_DISABLE) || (m_pTiles[Index].m_Index >= TILE_LFREEZE && m_pTiles[Index].m_Index <= TILE_LUNFREEZE))
return true; return true;
if(m_pFront && ((m_pFront[Index].m_Index >= TILE_FREEZE && m_pFront[Index].m_Index <= TILE_TELE_LASER_DISABLE) || (m_pFront[Index].m_Index >= TILE_LFREEZE && m_pFront[Index].m_Index <= TILE_LUNFREEZE))) if(m_pFront && (m_pFront[Index].m_Index == TILE_DEATH || (m_pFront[Index].m_Index >= TILE_FREEZE && m_pFront[Index].m_Index <= TILE_TELE_LASER_DISABLE) || (m_pFront[Index].m_Index >= TILE_LFREEZE && m_pFront[Index].m_Index <= TILE_LUNFREEZE)))
return true; return true;
if(m_pTele && (m_pTele[Index].m_Type == TILE_TELEIN || m_pTele[Index].m_Type == TILE_TELEINEVIL || m_pTele[Index].m_Type == TILE_TELECHECKINEVIL || m_pTele[Index].m_Type == TILE_TELECHECK || m_pTele[Index].m_Type == TILE_TELECHECKIN)) if(m_pTele && (m_pTele[Index].m_Type == TILE_TELEIN || m_pTele[Index].m_Type == TILE_TELEINEVIL || m_pTele[Index].m_Type == TILE_TELECHECKINEVIL || m_pTele[Index].m_Type == TILE_TELECHECK || m_pTele[Index].m_Type == TILE_TELECHECKIN))
return true; return true;

View file

@ -1415,13 +1415,14 @@ void CCharacter::SetTimeCheckpoint(int TimeCheckpoint)
} }
} }
void CCharacter::HandleTiles(int Index) void CCharacter::HandleTiles(int Index, bool *pStopProcessing)
{ {
int MapIndex = Index; int MapIndex = Index;
//int PureMapIndex = Collision()->GetPureMapIndex(m_Pos); //int PureMapIndex = Collision()->GetPureMapIndex(m_Pos);
m_TileIndex = Collision()->GetTileIndex(MapIndex); m_TileIndex = Collision()->GetTileIndex(MapIndex);
m_TileFIndex = Collision()->GetFTileIndex(MapIndex); m_TileFIndex = Collision()->GetFTileIndex(MapIndex);
m_MoveRestrictions = Collision()->GetMoveRestrictions(IsSwitchActiveCb, this, m_Pos, 18.0f, MapIndex); m_MoveRestrictions = Collision()->GetMoveRestrictions(IsSwitchActiveCb, this, m_Pos, 18.0f, MapIndex);
*pStopProcessing = false;
if(Index < 0) if(Index < 0)
{ {
m_LastRefillJumps = false; m_LastRefillJumps = false;
@ -1790,6 +1791,13 @@ void CCharacter::HandleTiles(int Index)
m_LastBonus = false; m_LastBonus = false;
} }
if((m_TileIndex == TILE_DEATH) || (m_TileFIndex == TILE_DEATH))
{
Die(m_pPlayer->GetCID(), WEAPON_WORLD);
*pStopProcessing = true;
return;
}
int z = Collision()->IsTeleport(MapIndex); int z = Collision()->IsTeleport(MapIndex);
if(!g_Config.m_SvOldTeleportHook && !g_Config.m_SvOldTeleportWeapons && z && !(*m_pTeleOuts)[z - 1].empty()) if(!g_Config.m_SvOldTeleportHook && !g_Config.m_SvOldTeleportWeapons && z && !(*m_pTeleOuts)[z - 1].empty())
{ {
@ -1797,6 +1805,7 @@ void CCharacter::HandleTiles(int Index)
return; return;
int TeleOut = m_Core.m_pWorld->RandomOr0((*m_pTeleOuts)[z - 1].size()); int TeleOut = m_Core.m_pWorld->RandomOr0((*m_pTeleOuts)[z - 1].size());
m_Core.m_Pos = (*m_pTeleOuts)[z - 1][TeleOut]; m_Core.m_Pos = (*m_pTeleOuts)[z - 1][TeleOut];
*pStopProcessing = true;
if(!g_Config.m_SvTeleportHoldHook) if(!g_Config.m_SvTeleportHoldHook)
{ {
ResetHook(); ResetHook();
@ -1812,6 +1821,7 @@ void CCharacter::HandleTiles(int Index)
return; return;
int TeleOut = m_Core.m_pWorld->RandomOr0((*m_pTeleOuts)[evilz - 1].size()); int TeleOut = m_Core.m_pWorld->RandomOr0((*m_pTeleOuts)[evilz - 1].size());
m_Core.m_Pos = (*m_pTeleOuts)[evilz - 1][TeleOut]; m_Core.m_Pos = (*m_pTeleOuts)[evilz - 1][TeleOut];
*pStopProcessing = true;
if(!g_Config.m_SvOldTeleportHook && !g_Config.m_SvOldTeleportWeapons) if(!g_Config.m_SvOldTeleportHook && !g_Config.m_SvOldTeleportWeapons)
{ {
m_Core.m_Vel = vec2(0, 0); m_Core.m_Vel = vec2(0, 0);
@ -1839,6 +1849,7 @@ void CCharacter::HandleTiles(int Index)
{ {
int TeleOut = m_Core.m_pWorld->RandomOr0((*m_pTeleCheckOuts)[k].size()); int TeleOut = m_Core.m_pWorld->RandomOr0((*m_pTeleCheckOuts)[k].size());
m_Core.m_Pos = (*m_pTeleCheckOuts)[k][TeleOut]; m_Core.m_Pos = (*m_pTeleCheckOuts)[k][TeleOut];
*pStopProcessing = true;
m_Core.m_Vel = vec2(0, 0); m_Core.m_Vel = vec2(0, 0);
if(!g_Config.m_SvTeleportHoldHook) if(!g_Config.m_SvTeleportHoldHook)
@ -1855,6 +1866,7 @@ void CCharacter::HandleTiles(int Index)
if(GameServer()->m_pController->CanSpawn(m_pPlayer->GetTeam(), &SpawnPos, GameServer()->GetDDRaceTeam(GetPlayer()->GetCID()))) if(GameServer()->m_pController->CanSpawn(m_pPlayer->GetTeam(), &SpawnPos, GameServer()->GetDDRaceTeam(GetPlayer()->GetCID())))
{ {
m_Core.m_Pos = SpawnPos; m_Core.m_Pos = SpawnPos;
*pStopProcessing = true;
m_Core.m_Vel = vec2(0, 0); m_Core.m_Vel = vec2(0, 0);
if(!g_Config.m_SvTeleportHoldHook) if(!g_Config.m_SvTeleportHoldHook)
@ -1876,6 +1888,7 @@ void CCharacter::HandleTiles(int Index)
{ {
int TeleOut = m_Core.m_pWorld->RandomOr0((*m_pTeleCheckOuts)[k].size()); int TeleOut = m_Core.m_pWorld->RandomOr0((*m_pTeleCheckOuts)[k].size());
m_Core.m_Pos = (*m_pTeleCheckOuts)[k][TeleOut]; m_Core.m_Pos = (*m_pTeleCheckOuts)[k][TeleOut];
*pStopProcessing = true;
if(!g_Config.m_SvTeleportHoldHook) if(!g_Config.m_SvTeleportHoldHook)
{ {
@ -1890,6 +1903,7 @@ void CCharacter::HandleTiles(int Index)
if(GameServer()->m_pController->CanSpawn(m_pPlayer->GetTeam(), &SpawnPos, GameServer()->GetDDRaceTeam(GetPlayer()->GetCID()))) if(GameServer()->m_pController->CanSpawn(m_pPlayer->GetTeam(), &SpawnPos, GameServer()->GetDDRaceTeam(GetPlayer()->GetCID())))
{ {
m_Core.m_Pos = SpawnPos; m_Core.m_Pos = SpawnPos;
*pStopProcessing = true;
if(!g_Config.m_SvTeleportHoldHook) if(!g_Config.m_SvTeleportHoldHook)
{ {
@ -2099,17 +2113,23 @@ void CCharacter::DDRacePostCoreTick()
{ {
for(int &Index : vIndices) for(int &Index : vIndices)
{ {
HandleTiles(Index); bool StopProcessing;
if(!m_Alive) HandleTiles(Index, &StopProcessing);
if(StopProcessing || !m_Alive)
{
return; return;
} }
} }
}
else else
{ {
HandleTiles(CurrentIndex); bool StopProcessing;
if(!m_Alive) HandleTiles(CurrentIndex, &StopProcessing);
if(StopProcessing || !m_Alive)
{
return; return;
} }
}
// teleport gun // teleport gun
if(m_TeleGunTeleport) if(m_TeleGunTeleport)

View file

@ -148,7 +148,7 @@ private:
void SnapCharacter(int SnappingClient, int ID); void SnapCharacter(int SnappingClient, int ID);
static bool IsSwitchActiveCb(int Number, void *pUser); static bool IsSwitchActiveCb(int Number, void *pUser);
void SetTimeCheckpoint(int TimeCheckpoint); void SetTimeCheckpoint(int TimeCheckpoint);
void HandleTiles(int Index); void HandleTiles(int Index, bool *pStopProcessing);
float m_Time; float m_Time;
int m_LastBroadcast; int m_LastBroadcast;
void DDRaceInit(); void DDRaceInit();