Add an option to remove weak hook & bounce

This commit is contained in:
Jupeyy 2022-07-19 18:34:49 +02:00
parent 2240ad2966
commit 88c4b69301
16 changed files with 87 additions and 8 deletions

View file

@ -26,7 +26,7 @@ GameInfoFlags = [
] ]
GameInfoFlags2 = [ GameInfoFlags2 = [
"ALLOW_X_SKINS", "GAMETYPE_CITY", "GAMETYPE_FDDRACE", "ENTITIES_FDDRACE", "HUD_HEALTH_ARMOR", "HUD_AMMO", "ALLOW_X_SKINS", "GAMETYPE_CITY", "GAMETYPE_FDDRACE", "ENTITIES_FDDRACE", "HUD_HEALTH_ARMOR", "HUD_AMMO",
"HUD_DDRACE", "HUD_DDRACE", "NO_WEAK_HOOK_AND_BOUNCE"
] ]
ExPlayerFlags = ["AFK", "PAUSED", "SPEC"] ExPlayerFlags = ["AFK", "PAUSED", "SPEC"]
ProjectileFlags = ["CLIENTID_BIT{}".format(i) for i in range(8)] + [ ProjectileFlags = ["CLIENTID_BIT{}".format(i) for i in range(8)] + [
@ -64,7 +64,7 @@ enum
enum enum
{ {
GAMEINFO_CURVERSION=7, GAMEINFO_CURVERSION=8,
}; };
''' '''

View file

@ -285,6 +285,8 @@ MACRO_CONFIG_INT(SvOldLaser, sv_old_laser, 0, 0, 1, CFGFLAG_SERVER | CFGFLAG_GAM
MACRO_CONFIG_INT(SvSlashMe, sv_slash_me, 0, 0, 1, CFGFLAG_SERVER, "Whether /me is active on the server or not") MACRO_CONFIG_INT(SvSlashMe, sv_slash_me, 0, 0, 1, CFGFLAG_SERVER, "Whether /me is active on the server or not")
MACRO_CONFIG_INT(SvRejoinTeam0, sv_rejoin_team_0, 1, 0, 1, CFGFLAG_SERVER, "Make a team automatically rejoin team 0 after finish (only if not locked)") MACRO_CONFIG_INT(SvRejoinTeam0, sv_rejoin_team_0, 1, 0, 1, CFGFLAG_SERVER, "Make a team automatically rejoin team 0 after finish (only if not locked)")
MACRO_CONFIG_INT(SvNoWeakHookAndBounce, sv_no_weak_hook_and_bounce, 0, 0, 1, CFGFLAG_SERVER | CFGFLAG_GAME, "Whether to use an alternative calculation for world ticks, that makes hook and bounce behave like all players have strong.")
MACRO_CONFIG_INT(ClReconnectTimeout, cl_reconnect_timeout, 120, 0, 600, CFGFLAG_CLIENT | CFGFLAG_SAVE, "How many seconds to wait before reconnecting (after timeout, 0 for off)") MACRO_CONFIG_INT(ClReconnectTimeout, cl_reconnect_timeout, 120, 0, 600, CFGFLAG_CLIENT | CFGFLAG_SAVE, "How many seconds to wait before reconnecting (after timeout, 0 for off)")
MACRO_CONFIG_INT(ClReconnectFull, cl_reconnect_full, 5, 0, 600, CFGFLAG_CLIENT | CFGFLAG_SAVE, "How many seconds to wait before reconnecting (when server is full, 0 for off)") MACRO_CONFIG_INT(ClReconnectFull, cl_reconnect_full, 5, 0, 600, CFGFLAG_CLIENT | CFGFLAG_SAVE, "How many seconds to wait before reconnecting (when server is full, 0 for off)")

View file

@ -1067,6 +1067,7 @@ static CGameInfo GetGameInfo(const CNetObj_GameInfoEx *pInfoEx, int InfoExSize,
Info.m_HudHealthArmor = true; Info.m_HudHealthArmor = true;
Info.m_HudAmmo = true; Info.m_HudAmmo = true;
Info.m_HudDDRace = false; Info.m_HudDDRace = false;
Info.m_NoWeakHookAndBounce = false;
if(Version >= 0) if(Version >= 0)
{ {
@ -1118,6 +1119,10 @@ static CGameInfo GetGameInfo(const CNetObj_GameInfoEx *pInfoEx, int InfoExSize,
Info.m_HudAmmo = Flags2 & GAMEINFOFLAG2_HUD_AMMO; Info.m_HudAmmo = Flags2 & GAMEINFOFLAG2_HUD_AMMO;
Info.m_HudDDRace = Flags2 & GAMEINFOFLAG2_HUD_DDRACE; Info.m_HudDDRace = Flags2 & GAMEINFOFLAG2_HUD_DDRACE;
} }
if(Version >= 8)
{
Info.m_NoWeakHookAndBounce = Flags2 & GAMEINFOFLAG2_NO_WEAK_HOOK_AND_BOUNCE;
}
return Info; return Info;
} }
@ -2265,6 +2270,7 @@ void CGameClient::UpdatePrediction()
m_GameWorld.m_WorldConfig.m_PredictFreeze = g_Config.m_ClPredictFreeze; m_GameWorld.m_WorldConfig.m_PredictFreeze = g_Config.m_ClPredictFreeze;
m_GameWorld.m_WorldConfig.m_PredictWeapons = AntiPingWeapons(); m_GameWorld.m_WorldConfig.m_PredictWeapons = AntiPingWeapons();
m_GameWorld.m_WorldConfig.m_BugDDRaceInput = m_GameInfo.m_BugDDRaceInput; m_GameWorld.m_WorldConfig.m_BugDDRaceInput = m_GameInfo.m_BugDDRaceInput;
m_GameWorld.m_WorldConfig.m_NoWeakHookAndBounce = m_GameInfo.m_NoWeakHookAndBounce;
// always update default tune zone, even without character // always update default tune zone, even without character
if(!m_GameWorld.m_WorldConfig.m_UseTuneZones) if(!m_GameWorld.m_WorldConfig.m_UseTuneZones)

View file

@ -94,6 +94,8 @@ public:
bool m_HudHealthArmor; bool m_HudHealthArmor;
bool m_HudAmmo; bool m_HudAmmo;
bool m_HudDDRace; bool m_HudDDRace;
bool m_NoWeakHookAndBounce;
}; };
class CSnapEntities class CSnapEntities

View file

@ -561,12 +561,24 @@ void CCharacter::ResetInput()
m_LatestPrevInput = m_LatestInput = m_Input; m_LatestPrevInput = m_LatestInput = m_Input;
} }
void CCharacter::Tick() void CCharacter::PreTick()
{ {
DDRaceTick(); DDRaceTick();
m_Core.m_Input = m_Input; m_Core.m_Input = m_Input;
m_Core.Tick(true); m_Core.Tick(true, !m_pGameWorld->m_WorldConfig.m_NoWeakHookAndBounce);
}
void CCharacter::Tick()
{
if(m_pGameWorld->m_WorldConfig.m_NoWeakHookAndBounce)
{
m_Core.TickDeferred();
}
else
{
PreTick();
}
// handle Weapons // handle Weapons
HandleWeapons(); HandleWeapons();

View file

@ -36,6 +36,7 @@ public:
//character's size //character's size
static const int ms_PhysSize = 28; static const int ms_PhysSize = 28;
void PreTick() override;
void Tick() override; void Tick() override;
void TickDeferred() override; void TickDeferred() override;

View file

@ -52,6 +52,7 @@ public:
float GetProximityRadius() const { return m_ProximityRadius; } float GetProximityRadius() const { return m_ProximityRadius; }
void Destroy() { delete this; } void Destroy() { delete this; }
virtual void PreTick() {}
virtual void Tick() {} virtual void Tick() {}
virtual void TickDeferred() {} virtual void TickDeferred() {}

View file

@ -187,6 +187,17 @@ bool distCompare(std::pair<float, int> a, std::pair<float, int> b)
void CGameWorld::Tick() void CGameWorld::Tick()
{ {
// update all objects // update all objects
if(m_WorldConfig.m_NoWeakHookAndBounce)
{
for(auto *pEnt : m_apFirstEntityTypes)
for(; pEnt;)
{
m_pNextTraverseEntity = pEnt->m_pNextTypeEntity;
pEnt->PreTick();
pEnt = m_pNextTraverseEntity;
}
}
for(auto *pEnt : m_apFirstEntityTypes) for(auto *pEnt : m_apFirstEntityTypes)
for(; pEnt;) for(; pEnt;)
{ {

View file

@ -77,6 +77,7 @@ public:
bool m_IsSolo; bool m_IsSolo;
bool m_UseTuneZones; bool m_UseTuneZones;
bool m_BugDDRaceInput; bool m_BugDDRaceInput;
bool m_NoWeakHookAndBounce;
} m_WorldConfig; } m_WorldConfig;
bool m_IsValidCopy; bool m_IsValidCopy;

View file

@ -116,7 +116,7 @@ void CCharacterCore::Reset()
m_Input.m_TargetY = -1; m_Input.m_TargetY = -1;
} }
void CCharacterCore::Tick(bool UseInput) void CCharacterCore::Tick(bool UseInput, bool DoDeferredTick)
{ {
m_MoveRestrictions = m_pCollision->GetMoveRestrictions(UseInput ? IsSwitchActiveCb : 0, this, m_Pos); m_MoveRestrictions = m_pCollision->GetMoveRestrictions(UseInput ? IsSwitchActiveCb : 0, this, m_Pos);
m_TriggeredEvents = 0; m_TriggeredEvents = 0;
@ -387,6 +387,12 @@ void CCharacterCore::Tick(bool UseInput)
} }
} }
if(DoDeferredTick)
TickDeferred();
}
void CCharacterCore::TickDeferred()
{
if(m_pWorld) if(m_pWorld)
{ {
for(int i = 0; i < MAX_CLIENTS; i++) for(int i = 0; i < MAX_CLIENTS; i++)

View file

@ -269,7 +269,8 @@ public:
void Init(CWorldCore *pWorld, CCollision *pCollision, CTeamsCore *pTeams = nullptr, std::map<int, std::vector<vec2>> *pTeleOuts = nullptr); void Init(CWorldCore *pWorld, CCollision *pCollision, CTeamsCore *pTeams = nullptr, std::map<int, std::vector<vec2>> *pTeleOuts = nullptr);
void Reset(); void Reset();
void Tick(bool UseInput); void TickDeferred();
void Tick(bool UseInput, bool DoDeferredTick = true);
void Move(); void Move();
void Read(const CNetObj_CharacterCore *pObjCore); void Read(const CNetObj_CharacterCore *pObjCore);

View file

@ -712,7 +712,7 @@ void CCharacter::ResetInput()
m_LatestPrevInput = m_LatestInput = m_Input; m_LatestPrevInput = m_LatestInput = m_Input;
} }
void CCharacter::Tick() void CCharacter::PreTick()
{ {
if(m_StartTime > Server()->Tick()) if(m_StartTime > Server()->Tick())
{ {
@ -738,7 +738,22 @@ void CCharacter::Tick()
Antibot()->OnCharacterTick(m_pPlayer->GetCID()); Antibot()->OnCharacterTick(m_pPlayer->GetCID());
m_Core.m_Input = m_Input; m_Core.m_Input = m_Input;
m_Core.Tick(true); m_Core.Tick(true, !g_Config.m_SvNoWeakHookAndBounce);
}
void CCharacter::Tick()
{
if(g_Config.m_SvNoWeakHookAndBounce)
{
if(m_Paused)
return;
m_Core.TickDeferred();
}
else
{
PreTick();
}
if(!m_PrevInput.m_Hook && m_Input.m_Hook && !(m_Core.m_TriggeredEvents & COREEVENT_HOOK_ATTACH_PLAYER)) if(!m_PrevInput.m_Hook && m_Input.m_Hook && !(m_Core.m_TriggeredEvents & COREEVENT_HOOK_ATTACH_PLAYER))
{ {

View file

@ -33,6 +33,7 @@ public:
void Reset() override; void Reset() override;
void Destroy() override; void Destroy() override;
void PreTick() override;
void Tick() override; void Tick() override;
void TickDeferred() override; void TickDeferred() override;
void TickPaused() override; void TickPaused() override;

View file

@ -86,6 +86,13 @@ public: // TODO: Maybe make protected
*/ */
virtual void Reset() {} virtual void Reset() {}
/*
Function: PreTick
Called to progress the entity before the next tick.
Can be used to prepare variables for all clients before the next tick is executed.
*/
virtual void PreTick() {}
/* /*
Function: Tick Function: Tick
Called to progress the entity to the next tick. Updates Called to progress the entity to the next tick. Updates

View file

@ -605,6 +605,8 @@ void IGameController::Snap(int SnappingClient)
GAMEINFOFLAG_ENTITIES_RACE | GAMEINFOFLAG_ENTITIES_RACE |
GAMEINFOFLAG_RACE; GAMEINFOFLAG_RACE;
pGameInfoEx->m_Flags2 = GAMEINFOFLAG2_HUD_DDRACE; pGameInfoEx->m_Flags2 = GAMEINFOFLAG2_HUD_DDRACE;
if(g_Config.m_SvNoWeakHookAndBounce)
pGameInfoEx->m_Flags2 |= GAMEINFOFLAG2_NO_WEAK_HOOK_AND_BOUNCE;
pGameInfoEx->m_Version = GAMEINFO_CURVERSION; pGameInfoEx->m_Version = GAMEINFO_CURVERSION;
if(Server()->IsSixup(SnappingClient)) if(Server()->IsSixup(SnappingClient))

View file

@ -268,6 +268,17 @@ void CGameWorld::Tick()
if(GameServer()->m_pController->IsForceBalanced()) if(GameServer()->m_pController->IsForceBalanced())
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Teams have been balanced"); GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Teams have been balanced");
// update all objects // update all objects
if(g_Config.m_SvNoWeakHookAndBounce)
{
for(auto *pEnt : m_apFirstEntityTypes)
for(; pEnt;)
{
m_pNextTraverseEntity = pEnt->m_pNextTypeEntity;
pEnt->PreTick();
pEnt = m_pNextTraverseEntity;
}
}
for(auto *pEnt : m_apFirstEntityTypes) for(auto *pEnt : m_apFirstEntityTypes)
for(; pEnt;) for(; pEnt;)
{ {