From e6b609c817354d09f014bad8153841f0dd4e0922 Mon Sep 17 00:00:00 2001 From: rtw1x1 Date: Fri, 19 Dec 2025 15:38:13 +0000 Subject: [PATCH] fix: POS_FIGHTING state --- src/common/service.h | 7 +++++++ src/game/char.cpp | 18 ++++++++++++++++++ src/game/char.h | 10 ++++++++++ src/game/char_battle.cpp | 34 ++++++++++++++++++++++++++++++++++ src/game/char_skill.cpp | 7 +++++++ 5 files changed, 76 insertions(+) diff --git a/src/common/service.h b/src/common/service.h index 2d85760..d1b1c2f 100644 --- a/src/common/service.h +++ b/src/common/service.h @@ -7,3 +7,10 @@ #define __PET_SYSTEM__ #define __UDP_BLOCK__ #endif + +/* +This fixes the POS_FIGHTING state, when a character will enter POS_FIGHTING state, +after 10s of no damage dealt, should've been switched to POS_STANDING state. +Files affected: char.cpp, char.h, char_battle.cpp, char_skill.cpp +*/ +#ifdef FIX_BATTLE_INACTIVITY_TIMEOUT \ No newline at end of file diff --git a/src/game/char.cpp b/src/game/char.cpp index 1b3dbfa..a501e2b 100644 --- a/src/game/char.cpp +++ b/src/game/char.cpp @@ -361,6 +361,10 @@ void CHARACTER::Initialize() m_bIsLoadedAffect = false; cannot_dead = false; +#ifdef FIX_BATTLE_INACTIVITY_TIMEOUT + m_dwLastCombatTime = 0; +#endif + #ifdef __PET_SYSTEM__ m_petSystem = 0; m_bIsPet = false; @@ -4060,6 +4064,20 @@ void CHARACTER::UpdateStateMachine(DWORD dwPulse) if (IsDead()) return; +#ifdef FIX_BATTLE_INACTIVITY_TIMEOUT + if (IsPC() && IsPosition(POS_FIGHTING)) + { + const DWORD now = get_dword_time(); + + // If we never set a combat time yet, set it now so timer can start. + if (m_dwLastCombatTime == 0) + m_dwLastCombatTime = now; + + if (now - m_dwLastCombatTime >= 10000) + SetVictim(NULL); // triggers battle_end() -> POS_STANDING + } +#endif + Update(); m_dwNextStatePulse = dwPulse + m_dwStateDuration; } diff --git a/src/game/char.h b/src/game/char.h index 6779b3a..667ae1c 100644 --- a/src/game/char.h +++ b/src/game/char.h @@ -2037,6 +2037,16 @@ class CHARACTER : public CEntity, public CFSM, public CHorseRider protected: int m_iLastPMPulse; int m_iPMCounter; + +#ifdef FIX_BATTLE_INACTIVITY_TIMEOUT + public: + void EnterCombat(); + void UpdateLastCombatTime() { m_dwLastCombatTime = get_dword_time(); } + DWORD GetLastCombatTime() const { return m_dwLastCombatTime; } + + private: + DWORD m_dwLastCombatTime; +#endif }; ESex GET_SEX(LPCHARACTER ch); diff --git a/src/game/char_battle.cpp b/src/game/char_battle.cpp index d962cff..5f6bde4 100644 --- a/src/game/char_battle.cpp +++ b/src/game/char_battle.cpp @@ -1592,6 +1592,24 @@ void CHARACTER::SendDamagePacket(LPCHARACTER pAttacker, int Damage, BYTE DamageF } } +#ifdef FIX_BATTLE_INACTIVITY_TIMEOUT +void CHARACTER::EnterCombat() +{ + if (!IsPC()) + return; + + if (!IsPosition(POS_FIGHTING)) + { + SetPosition(POS_FIGHTING); + SetNextStatePulse(1); + } + + // Start the 10s window if it hasn't started yet. + if (m_dwLastCombatTime == 0) + m_dwLastCombatTime = get_dword_time(); +} +#ifdef FIX_BATTLE_INACTIVITY_TIMEOUT + // // CHARACTER::Damage 메소드는 this가 데미지를 입게 한다. // @@ -2287,6 +2305,22 @@ bool CHARACTER::Damage(LPCHARACTER pAttacker, int dam, EDamageType type) // retu // if (!cannot_dead) { +#ifdef FIX_BATTLE_INACTIVITY_TIMEOUT + // REAL combat activity only: final damage > 0 + if (dam > 0) + { + // Victim received real damage + UpdateLastCombatTime(); + EnterCombat(); + + // Attacker dealt real damage + if (pAttacker) + { + pAttacker->UpdateLastCombatTime(); + pAttacker->EnterCombat(); + } + } +#endif PointChange(POINT_HP, -dam, false); } diff --git a/src/game/char_skill.cpp b/src/game/char_skill.cpp index b68edbc..5c690bc 100644 --- a/src/game/char_skill.cpp +++ b/src/game/char_skill.cpp @@ -2462,6 +2462,13 @@ bool CHARACTER::UseSkill(DWORD dwVnum, LPCHARACTER pkVictim, bool bUseGrandMaste if (!pkSk) return false; +#ifdef FIX_BATTLE_INACTIVITY_TIMEOUT + if (IsPC() && IS_SET(pkSk->dwFlag, SKILL_FLAG_ATTACK)) + { + EnterCombat(); + } +#endif + if (bCanUseHorseSkill && pkSk->dwType != SKILL_TYPE_HORSE) return BATTLE_NONE;