From b564110675d8c8be1433dab3cdea91f354d4a33b Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Tue, 24 Sep 2024 01:16:40 +0200 Subject: [PATCH] Make invincible players immune to freeze, death and teleport tiles and give them unlimited jumps Specifically: * Ignore freeze, deep freeze, deep unfreeze, live freeze, and live unfreeze tiles * Ignore also the switched variants of those tiles * Allow movement when deep and live frozen * Ignore death tiles * Ignore red tele, blue tele, red checkpoint tele, and blue checkpoint tele tiles * Unlimited jumps * Disable /rescue Switches, doors, draggers, etc. are not disabled for invincible players in this patch --- .../client/prediction/entities/character.cpp | 30 ++++++------- src/game/server/entities/character.cpp | 44 ++++++++++--------- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/game/client/prediction/entities/character.cpp b/src/game/client/prediction/entities/character.cpp index 8ce77b67e..a3369651b 100644 --- a/src/game/client/prediction/entities/character.cpp +++ b/src/game/client/prediction/entities/character.cpp @@ -757,19 +757,19 @@ void CCharacter::HandleTiles(int Index) Switchers()[Collision()->GetSwitchNumber(MapIndex)].m_aType[Team()] = TILE_SWITCHCLOSE; Switchers()[Collision()->GetSwitchNumber(MapIndex)].m_aLastUpdateTick[Team()] = GameWorld()->GameTick(); } - else if(Collision()->GetSwitchType(MapIndex) == TILE_FREEZE && Team() != TEAM_SUPER) + else if(Collision()->GetSwitchType(MapIndex) == TILE_FREEZE && Team() != TEAM_SUPER && !m_Core.m_Invincible) { if(Collision()->GetSwitchNumber(MapIndex) == 0 || Switchers()[Collision()->GetSwitchNumber(MapIndex)].m_aStatus[Team()]) { Freeze(Collision()->GetSwitchDelay(MapIndex)); } } - else if(Collision()->GetSwitchType(MapIndex) == TILE_DFREEZE && Team() != TEAM_SUPER) + else if(Collision()->GetSwitchType(MapIndex) == TILE_DFREEZE && Team() != TEAM_SUPER && !m_Core.m_Invincible) { if(Collision()->GetSwitchNumber(MapIndex) == 0 || Switchers()[Collision()->GetSwitchNumber(MapIndex)].m_aStatus[Team()]) m_Core.m_DeepFrozen = true; } - else if(Collision()->GetSwitchType(MapIndex) == TILE_DUNFREEZE && Team() != TEAM_SUPER) + else if(Collision()->GetSwitchType(MapIndex) == TILE_DUNFREEZE && Team() != TEAM_SUPER && !m_Core.m_Invincible) { if(Collision()->GetSwitchNumber(MapIndex) == 0 || Switchers()[Collision()->GetSwitchNumber(MapIndex)].m_aStatus[Team()]) m_Core.m_DeepFrozen = false; @@ -817,14 +817,14 @@ void CCharacter::HandleTiles(int Index) if(NewJumps != m_Core.m_Jumps) m_Core.m_Jumps = NewJumps; } - else if(Collision()->GetSwitchType(MapIndex) == TILE_LFREEZE && Team() != TEAM_SUPER) + else if(Collision()->GetSwitchType(MapIndex) == TILE_LFREEZE && Team() != TEAM_SUPER && !m_Core.m_Invincible) { if(Collision()->GetSwitchNumber(MapIndex) == 0 || Switchers()[Collision()->GetSwitchNumber(MapIndex)].m_aStatus[Team()]) { m_Core.m_LiveFrozen = true; } } - else if(Collision()->GetSwitchType(MapIndex) == TILE_LUNFREEZE && Team() != TEAM_SUPER) + else if(Collision()->GetSwitchType(MapIndex) == TILE_LUNFREEZE && Team() != TEAM_SUPER && !m_Core.m_Invincible) { if(Collision()->GetSwitchNumber(MapIndex) == 0 || Switchers()[Collision()->GetSwitchNumber(MapIndex)].m_aStatus[Team()]) { @@ -833,7 +833,7 @@ void CCharacter::HandleTiles(int Index) } // freeze - if(((m_TileIndex == TILE_FREEZE) || (m_TileFIndex == TILE_FREEZE)) && !m_Core.m_Super && !m_Core.m_DeepFrozen) + if(((m_TileIndex == TILE_FREEZE) || (m_TileFIndex == TILE_FREEZE)) && !m_Core.m_Super && !m_Core.m_Invincible && !m_Core.m_DeepFrozen) { Freeze(); } @@ -843,21 +843,21 @@ void CCharacter::HandleTiles(int Index) } // deep freeze - if(((m_TileIndex == TILE_DFREEZE) || (m_TileFIndex == TILE_DFREEZE)) && !m_Core.m_Super && !m_Core.m_DeepFrozen) + if(((m_TileIndex == TILE_DFREEZE) || (m_TileFIndex == TILE_DFREEZE)) && !m_Core.m_Super && !m_Core.m_Invincible && !m_Core.m_DeepFrozen) { m_Core.m_DeepFrozen = true; } - else if(((m_TileIndex == TILE_DUNFREEZE) || (m_TileFIndex == TILE_DUNFREEZE)) && !m_Core.m_Super && m_Core.m_DeepFrozen) + else if(((m_TileIndex == TILE_DUNFREEZE) || (m_TileFIndex == TILE_DUNFREEZE)) && !m_Core.m_Super && !m_Core.m_Invincible && m_Core.m_DeepFrozen) { m_Core.m_DeepFrozen = false; } // live freeze - if(((m_TileIndex == TILE_LFREEZE) || (m_TileFIndex == TILE_LFREEZE)) && !m_Core.m_Super) + if(((m_TileIndex == TILE_LFREEZE) || (m_TileFIndex == TILE_LFREEZE)) && !m_Core.m_Super && !m_Core.m_Invincible) { m_Core.m_LiveFrozen = true; } - else if(((m_TileIndex == TILE_LUNFREEZE) || (m_TileFIndex == TILE_LUNFREEZE)) && !m_Core.m_Super) + else if(((m_TileIndex == TILE_LUNFREEZE) || (m_TileFIndex == TILE_LUNFREEZE)) && !m_Core.m_Super && !m_Core.m_Invincible) { m_Core.m_LiveFrozen = false; } @@ -959,7 +959,7 @@ void CCharacter::HandleTuneLayer() void CCharacter::DDRaceTick() { mem_copy(&m_Input, &m_SavedInput, sizeof(m_Input)); - if(m_Core.m_LiveFrozen && !m_CanMoveInFreeze && !m_Core.m_Super) + if(m_Core.m_LiveFrozen && !m_CanMoveInFreeze && !m_Core.m_Super && !m_Core.m_Invincible) { m_Input.m_Direction = 0; m_Input.m_Jump = 0; @@ -1007,7 +1007,7 @@ void CCharacter::DDRacePostCoreTick() m_FrozenLastTick = false; - if(m_Core.m_DeepFrozen && !m_Core.m_Super) + if(m_Core.m_DeepFrozen && !m_Core.m_Super && !m_Core.m_Invincible) Freeze(); // following jump rules can be overridden by tiles, like Refill Jumps, Stopper and Wall Jump @@ -1032,9 +1032,9 @@ void CCharacter::DDRacePostCoreTick() m_Core.m_Jumped = 1; } - if((m_Core.m_Super || m_Core.m_EndlessJump) && m_Core.m_Jumped > 1) + if((m_Core.m_Super || m_Core.m_Invincible || m_Core.m_EndlessJump) && m_Core.m_Jumped > 1) { - // Super players and players with infinite jumps always have light feet + // Super players, invincible players and players with infinite jumps always have light feet m_Core.m_Jumped = 1; } @@ -1056,7 +1056,7 @@ bool CCharacter::Freeze(int Seconds) { if(!GameWorld()->m_WorldConfig.m_PredictFreeze) return false; - if(Seconds <= 0 || m_Core.m_Super || m_FreezeTime > Seconds * GameWorld()->GameTickSpeed()) + if(Seconds <= 0 || m_Core.m_Super || m_Core.m_Invincible || m_FreezeTime > Seconds * GameWorld()->GameTickSpeed()) return false; if(m_Core.m_FreezeStart < GameWorld()->GameTick() - GameWorld()->GameTickSpeed()) { diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 214228809..fa1d620ef 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -199,6 +199,8 @@ void CCharacter::SetInvincible(bool Invincible) SetSuper(false); m_Core.m_Invincible = Invincible; + if(Invincible) + UnFreeze(); } void CCharacter::SetLiveFrozen(bool Active) @@ -1377,7 +1379,7 @@ void CCharacter::HandleSkippableTiles(int Index) Collision()->GetFCollisionAt(m_Pos.x + GetProximityRadius() / 3.f, m_Pos.y + GetProximityRadius() / 3.f) == TILE_DEATH || Collision()->GetFCollisionAt(m_Pos.x - GetProximityRadius() / 3.f, m_Pos.y - GetProximityRadius() / 3.f) == TILE_DEATH || Collision()->GetFCollisionAt(m_Pos.x - GetProximityRadius() / 3.f, m_Pos.y + GetProximityRadius() / 3.f) == TILE_DEATH) && - !m_Core.m_Super && !(Team() && Teams()->TeeFinished(m_pPlayer->GetCid()))) + !m_Core.m_Super && !m_Core.m_Invincible && !(Team() && Teams()->TeeFinished(m_pPlayer->GetCid()))) { Die(m_pPlayer->GetCid(), WEAPON_WORLD); return; @@ -1507,7 +1509,7 @@ void CCharacter::HandleTiles(int Index) return; // freeze - if(((m_TileIndex == TILE_FREEZE) || (m_TileFIndex == TILE_FREEZE)) && !m_Core.m_Super && !m_Core.m_DeepFrozen) + if(((m_TileIndex == TILE_FREEZE) || (m_TileFIndex == TILE_FREEZE)) && !m_Core.m_Super && !m_Core.m_Invincible && !m_Core.m_DeepFrozen) { Freeze(); } @@ -1515,17 +1517,17 @@ void CCharacter::HandleTiles(int Index) UnFreeze(); // deep freeze - if(((m_TileIndex == TILE_DFREEZE) || (m_TileFIndex == TILE_DFREEZE)) && !m_Core.m_Super && !m_Core.m_DeepFrozen) + if(((m_TileIndex == TILE_DFREEZE) || (m_TileFIndex == TILE_DFREEZE)) && !m_Core.m_Super && !m_Core.m_Invincible && !m_Core.m_DeepFrozen) m_Core.m_DeepFrozen = true; - else if(((m_TileIndex == TILE_DUNFREEZE) || (m_TileFIndex == TILE_DUNFREEZE)) && !m_Core.m_Super && m_Core.m_DeepFrozen) + else if(((m_TileIndex == TILE_DUNFREEZE) || (m_TileFIndex == TILE_DUNFREEZE)) && !m_Core.m_Super && !m_Core.m_Invincible && m_Core.m_DeepFrozen) m_Core.m_DeepFrozen = false; // live freeze - if(((m_TileIndex == TILE_LFREEZE) || (m_TileFIndex == TILE_LFREEZE)) && !m_Core.m_Super) + if(((m_TileIndex == TILE_LFREEZE) || (m_TileFIndex == TILE_LFREEZE)) && !m_Core.m_Super && !m_Core.m_Invincible) { m_Core.m_LiveFrozen = true; } - else if(((m_TileIndex == TILE_LUNFREEZE) || (m_TileFIndex == TILE_LUNFREEZE)) && !m_Core.m_Super) + else if(((m_TileIndex == TILE_LUNFREEZE) || (m_TileFIndex == TILE_LUNFREEZE)) && !m_Core.m_Super && !m_Core.m_Invincible) { m_Core.m_LiveFrozen = false; } @@ -1706,31 +1708,31 @@ void CCharacter::HandleTiles(int Index) Switchers()[Collision()->GetSwitchNumber(MapIndex)].m_aType[Team()] = TILE_SWITCHCLOSE; Switchers()[Collision()->GetSwitchNumber(MapIndex)].m_aLastUpdateTick[Team()] = Server()->Tick(); } - else if(Collision()->GetSwitchType(MapIndex) == TILE_FREEZE && Team() != TEAM_SUPER) + else if(Collision()->GetSwitchType(MapIndex) == TILE_FREEZE && Team() != TEAM_SUPER && !m_Core.m_Invincible) { if(Collision()->GetSwitchNumber(MapIndex) == 0 || Switchers()[Collision()->GetSwitchNumber(MapIndex)].m_aStatus[Team()]) { Freeze(Collision()->GetSwitchDelay(MapIndex)); } } - else if(Collision()->GetSwitchType(MapIndex) == TILE_DFREEZE && Team() != TEAM_SUPER) + else if(Collision()->GetSwitchType(MapIndex) == TILE_DFREEZE && Team() != TEAM_SUPER && !m_Core.m_Invincible) { if(Collision()->GetSwitchNumber(MapIndex) == 0 || Switchers()[Collision()->GetSwitchNumber(MapIndex)].m_aStatus[Team()]) m_Core.m_DeepFrozen = true; } - else if(Collision()->GetSwitchType(MapIndex) == TILE_DUNFREEZE && Team() != TEAM_SUPER) + else if(Collision()->GetSwitchType(MapIndex) == TILE_DUNFREEZE && Team() != TEAM_SUPER && !m_Core.m_Invincible) { if(Collision()->GetSwitchNumber(MapIndex) == 0 || Switchers()[Collision()->GetSwitchNumber(MapIndex)].m_aStatus[Team()]) m_Core.m_DeepFrozen = false; } - else if(Collision()->GetSwitchType(MapIndex) == TILE_LFREEZE && Team() != TEAM_SUPER) + else if(Collision()->GetSwitchType(MapIndex) == TILE_LFREEZE && Team() != TEAM_SUPER && !m_Core.m_Invincible) { if(Collision()->GetSwitchNumber(MapIndex) == 0 || Switchers()[Collision()->GetSwitchNumber(MapIndex)].m_aStatus[Team()]) { m_Core.m_LiveFrozen = true; } } - else if(Collision()->GetSwitchType(MapIndex) == TILE_LUNFREEZE && Team() != TEAM_SUPER) + else if(Collision()->GetSwitchType(MapIndex) == TILE_LUNFREEZE && Team() != TEAM_SUPER && !m_Core.m_Invincible) { if(Collision()->GetSwitchNumber(MapIndex) == 0 || Switchers()[Collision()->GetSwitchNumber(MapIndex)].m_aStatus[Team()]) { @@ -1862,7 +1864,7 @@ void CCharacter::HandleTiles(int Index) int z = Collision()->IsTeleport(MapIndex); if(!g_Config.m_SvOldTeleportHook && !g_Config.m_SvOldTeleportWeapons && z && !Collision()->TeleOuts(z - 1).empty()) { - if(m_Core.m_Super) + if(m_Core.m_Super || m_Core.m_Invincible) return; int TeleOut = GameWorld()->m_Core.RandomOr0(Collision()->TeleOuts(z - 1).size()); m_Core.m_Pos = Collision()->TeleOuts(z - 1)[TeleOut]; @@ -1877,7 +1879,7 @@ void CCharacter::HandleTiles(int Index) int evilz = Collision()->IsEvilTeleport(MapIndex); if(evilz && !Collision()->TeleOuts(evilz - 1).empty()) { - if(m_Core.m_Super) + if(m_Core.m_Super || m_Core.m_Invincible) return; int TeleOut = GameWorld()->m_Core.RandomOr0(Collision()->TeleOuts(evilz - 1).size()); m_Core.m_Pos = Collision()->TeleOuts(evilz - 1)[TeleOut]; @@ -1899,7 +1901,7 @@ void CCharacter::HandleTiles(int Index) } if(Collision()->IsCheckEvilTeleport(MapIndex)) { - if(m_Core.m_Super) + if(m_Core.m_Super || m_Core.m_Invincible) return; // first check if there is a TeleCheckOut for the current recorded checkpoint, if not check previous checkpoints for(int k = m_TeleCheckpoint - 1; k >= 0; k--) @@ -1936,7 +1938,7 @@ void CCharacter::HandleTiles(int Index) } if(Collision()->IsCheckTeleport(MapIndex)) { - if(m_Core.m_Super) + if(m_Core.m_Super || m_Core.m_Invincible) return; // first check if there is a TeleCheckOut for the current recorded checkpoint, if not check previous checkpoints for(int k = m_TeleCheckpoint - 1; k >= 0; k--) @@ -2082,7 +2084,7 @@ void CCharacter::DDRaceTick() if(m_Input.m_Direction != 0 || m_Input.m_Jump != 0) m_LastMove = Server()->Tick(); - if(m_Core.m_LiveFrozen && !m_Core.m_Super) + if(m_Core.m_LiveFrozen && !m_Core.m_Super && !m_Core.m_Invincible) { m_Input.m_Direction = 0; m_Input.m_Jump = 0; @@ -2136,7 +2138,7 @@ void CCharacter::DDRacePostCoreTick() m_FrozenLastTick = false; - if(m_Core.m_DeepFrozen && !m_Core.m_Super) + if(m_Core.m_DeepFrozen && !m_Core.m_Super && !m_Core.m_Invincible) Freeze(); // following jump rules can be overridden by tiles, like Refill Jumps, Stopper and Wall Jump @@ -2161,9 +2163,9 @@ void CCharacter::DDRacePostCoreTick() m_Core.m_Jumped = 1; } - if((m_Core.m_Super || m_Core.m_EndlessJump) && m_Core.m_Jumped > 1) + if((m_Core.m_Super || m_Core.m_Invincible || m_Core.m_EndlessJump) && m_Core.m_Jumped > 1) { - // Super players and players with infinite jumps always have light feet + // Super players, invincible players and players with infinite jumps always have light feet m_Core.m_Jumped = 1; } @@ -2208,7 +2210,7 @@ void CCharacter::DDRacePostCoreTick() bool CCharacter::Freeze(int Seconds) { - if(Seconds <= 0 || m_Core.m_Super || m_FreezeTime > Seconds * Server()->TickSpeed()) + if(Seconds <= 0 || m_Core.m_Super || m_Core.m_Invincible || m_FreezeTime > Seconds * Server()->TickSpeed()) return false; if(m_FreezeTime == 0 || m_Core.m_FreezeStart < Server()->Tick() - Server()->TickSpeed()) { @@ -2382,7 +2384,7 @@ void CCharacter::DDRaceInit() void CCharacter::Rescue() { - if(m_SetSavePos[GetPlayer()->m_RescueMode] && !m_Core.m_Super) + if(m_SetSavePos[GetPlayer()->m_RescueMode] && !m_Core.m_Super && !m_Core.m_Invincible) { if(m_LastRescue + (int64_t)g_Config.m_SvRescueDelay * Server()->TickSpeed() > Server()->Tick()) {