MR-2: Auto-revert POS_FIGHTING after inactivity + Realtime character level updates
This commit is contained in:
@@ -3,17 +3,19 @@
|
||||
|
||||
#define ENABLE_AUTODETECT_INTERNAL_IP
|
||||
#define ENABLE_PROXY_IP
|
||||
#define _IMPROVED_PACKET_ENCRYPTION_ // 패킷 암호화 개선
|
||||
#define _IMPROVED_PACKET_ENCRYPTION_ // 패킷 암호화 개선
|
||||
#define __PET_SYSTEM__
|
||||
#define __UDP_BLOCK__
|
||||
|
||||
#define FIX_HEADER_CG_MARK_LOGIN // Fix for syserr error header 100 (login phase does not handle this packet! header 100);
|
||||
#define FIX_NEG_CMD_CORE_DOWNER // Fix core downer after negative command value (mobs, items, etc...)
|
||||
#define FIX_NEG_HP // Fix negative HP value when dead
|
||||
#define FIX_MESSENGER_ACTION_SYNC // Fix companion messenger updates when being deleted by a friend
|
||||
#define FIX_HEADER_CG_MARK_LOGIN // Fix for syserr error header 100 (login phase does not handle this packet! header 100);
|
||||
#define FIX_NEG_CMD_CORE_DOWNER // Fix core downer after negative command value (mobs, items, etc...)
|
||||
#define FIX_NEG_HP // Fix negative HP value when dead
|
||||
#define FIX_MESSENGER_ACTION_SYNC // Fix companion messenger updates when being deleted by a friend
|
||||
#define CHAR_SELECT_STATS_IMPROVEMENT // Improve stats values in character select screen
|
||||
#define CROSS_CHANNEL_FRIEND_REQUEST // Allow friend requests across different channels
|
||||
#define FIX_REFRESH_SKILL_COOLDOWN // Fix cooldown display time on skill slots
|
||||
#define FIX_REFRESH_SKILL_COOLDOWN // Fix cooldown display time on skill slots
|
||||
#define FIX_BOOK_READING_FOR_MAX_LEVEL // Disable experience point deduction for reading a book when in max level
|
||||
#define FIX_BATTLE_INACTIVITY_TIMEOUT // by #tw1x1: Add battle mode inactivity timeout and reset to standing
|
||||
#define __BL_LEVEL_FIX__ // Live character level updates
|
||||
|
||||
#endif
|
||||
|
||||
@@ -361,6 +361,12 @@ void CHARACTER::Initialize()
|
||||
m_bIsLoadedAffect = false;
|
||||
cannot_dead = false;
|
||||
|
||||
#ifdef FIX_BATTLE_INACTIVITY_TIMEOUT
|
||||
// tw1x1: POS_FIGHTING timer fix
|
||||
m_dwLastCombatTime = 0;
|
||||
// tw1x1: end
|
||||
#endif
|
||||
|
||||
#ifdef __PET_SYSTEM__
|
||||
m_petSystem = 0;
|
||||
m_bIsPet = false;
|
||||
@@ -2650,6 +2656,19 @@ bool CHARACTER::Sync(long x, long y)
|
||||
SetRotationToXY(x, y);
|
||||
SetXYZ(x, y, 0);
|
||||
|
||||
#ifdef TW1X1_TEST
|
||||
m_posDest.x = m_posStart.x = x;
|
||||
m_posDest.y = m_posStart.y = y;
|
||||
|
||||
// If we were moving, stop movement state after a correction.
|
||||
// Client will resend intent if it still wants to move.
|
||||
if (IsState(m_stateMove))
|
||||
{
|
||||
m_dwStateDuration = 0;
|
||||
GotoState(m_stateIdle);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (GetDungeon())
|
||||
{
|
||||
// 던젼용 이벤트 속성 변화
|
||||
@@ -4091,6 +4110,22 @@ void CHARACTER::UpdateStateMachine(DWORD dwPulse)
|
||||
if (IsDead())
|
||||
return;
|
||||
|
||||
#ifdef FIX_BATTLE_INACTIVITY_TIMEOUT
|
||||
// tw1x1: POS_FIGHTING timer fix
|
||||
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
|
||||
}
|
||||
// tw1x1: end
|
||||
#endif
|
||||
|
||||
Update();
|
||||
m_dwNextStatePulse = dwPulse + m_dwStateDuration;
|
||||
}
|
||||
@@ -5907,7 +5942,11 @@ void CHARACTER::ResetPoint(int iLv)
|
||||
{
|
||||
BYTE bJob = GetJob();
|
||||
|
||||
#if defined(__BL_LEVEL_FIX__)
|
||||
PointChange(POINT_LEVEL, iLv - GetLevel(), false, true);
|
||||
#else
|
||||
PointChange(POINT_LEVEL, iLv - GetLevel());
|
||||
#endif
|
||||
|
||||
SetRealPoint(POINT_ST, JobInitialPoints[bJob].st);
|
||||
SetPoint(POINT_ST, GetRealPoint(POINT_ST));
|
||||
|
||||
@@ -2044,6 +2044,18 @@ class CHARACTER : public CEntity, public CFSM, public CHorseRider
|
||||
protected:
|
||||
int m_iLastPMPulse;
|
||||
int m_iPMCounter;
|
||||
|
||||
#ifdef FIX_BATTLE_INACTIVITY_TIMEOUT
|
||||
// tw1x1: POS_FIGHTING timer fix
|
||||
public:
|
||||
void EnterCombat();
|
||||
void UpdateLastCombatTime() { m_dwLastCombatTime = get_dword_time(); }
|
||||
DWORD GetLastCombatTime() const { return m_dwLastCombatTime; }
|
||||
|
||||
private:
|
||||
DWORD m_dwLastCombatTime;
|
||||
// tw1x1: end
|
||||
#endif
|
||||
};
|
||||
|
||||
ESex GET_SEX(LPCHARACTER ch);
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "DragonLair.h"
|
||||
#include <random>
|
||||
#include <algorithm>
|
||||
|
||||
DWORD AdjustExpByLevel(const LPCHARACTER ch, const DWORD exp)
|
||||
{
|
||||
if (PLAYER_EXP_TABLE_MAX < ch->GetLevel())
|
||||
@@ -208,8 +209,11 @@ bool CHARACTER::Attack(LPCHARACTER pkVictim, BYTE bType)
|
||||
|
||||
pkVictim->SetSyncOwner(this);
|
||||
|
||||
// Always ensure the victim is in fighting state and has the inactivity timer running
|
||||
if (pkVictim->CanBeginFight())
|
||||
{
|
||||
pkVictim->BeginFight(this);
|
||||
}
|
||||
|
||||
int iRet;
|
||||
|
||||
@@ -1608,12 +1612,29 @@ void CHARACTER::SendDamagePacket(LPCHARACTER pAttacker, int Damage, BYTE DamageF
|
||||
// true : dead
|
||||
// false : not dead yet
|
||||
//
|
||||
|
||||
#ifdef FIX_BATTLE_INACTIVITY_TIMEOUT
|
||||
// tw1x1: POS_FIGHTING timer fix
|
||||
void CHARACTER::EnterCombat()
|
||||
{
|
||||
if (!IsPC())
|
||||
return;
|
||||
|
||||
if (!IsPosition(POS_FIGHTING))
|
||||
SetPosition(POS_FIGHTING);
|
||||
|
||||
SetNextStatePulse(1);
|
||||
}
|
||||
// tw1x1: end
|
||||
#endif
|
||||
|
||||
bool CHARACTER::Damage(LPCHARACTER pAttacker, int dam, EDamageType type) // returns true if dead
|
||||
{
|
||||
if (DAMAGE_TYPE_MAGIC == type)
|
||||
{
|
||||
dam = (int)((float)dam * (100 + (pAttacker->GetPoint(POINT_MAGIC_ATT_BONUS_PER) + pAttacker->GetPoint(POINT_MELEE_MAGIC_ATT_BONUS_PER))) / 100.f + 0.5f);
|
||||
}
|
||||
|
||||
if (GetRaceNum() == 5001)
|
||||
{
|
||||
bool bDropMoney = false;
|
||||
@@ -2295,6 +2316,26 @@ bool CHARACTER::Damage(LPCHARACTER pAttacker, int dam, EDamageType type) // retu
|
||||
if (GetHP() - dam <= 0)
|
||||
dam = GetHP();
|
||||
#endif
|
||||
|
||||
#ifdef FIX_BATTLE_INACTIVITY_TIMEOUT
|
||||
// tw1x1: POS_FIGHTING timer fix
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
// tw1x1: end
|
||||
#endif
|
||||
|
||||
PointChange(POINT_HP, -dam, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -2001,18 +2001,7 @@ int CHARACTER::ComputeSkill(DWORD dwVnum, LPCHARACTER pkVictim, BYTE bSkillLevel
|
||||
|
||||
// 말을 타고있지만 스킬은 사용할 수 없는 상태라면 return
|
||||
if (false == bCanUseHorseSkill && true == IsRiding())
|
||||
#ifdef FIX_REFRESH_SKILL_COOLDOWN
|
||||
{
|
||||
const bool bToggleSkill = pkSk && IS_SET(pkSk->dwFlag, SKILL_FLAG_TOGGLE);
|
||||
const bool bToggleActive = bToggleSkill ? (dwVnum == SKILL_COMBO ? m_bComboIndex != 0 : FindAffect(dwVnum) != nullptr) : false;
|
||||
|
||||
// Allow only deactivation of already-active toggles (combo or other) while riding
|
||||
if (!bToggleActive)
|
||||
return BATTLE_NONE;
|
||||
}
|
||||
#else
|
||||
return BATTLE_NONE;
|
||||
#endif
|
||||
|
||||
if (IsPolymorphed())
|
||||
return BATTLE_NONE;
|
||||
@@ -2023,14 +2012,7 @@ int CHARACTER::ComputeSkill(DWORD dwVnum, LPCHARACTER pkVictim, BYTE bSkillLevel
|
||||
if (!pkSk)
|
||||
return BATTLE_NONE;
|
||||
|
||||
#ifdef FIX_REFRESH_SKILL_COOLDOWN
|
||||
const bool bIsToggleSkill = IS_SET(pkSk->dwFlag, SKILL_FLAG_TOGGLE);
|
||||
const bool bToggleActive = bIsToggleSkill ? (dwVnum == SKILL_COMBO ? m_bComboIndex != 0 : FindAffect(dwVnum) != nullptr) : false;
|
||||
|
||||
if (bCanUseHorseSkill && pkSk->dwType != SKILL_TYPE_HORSE && !(bIsToggleSkill && bToggleActive))
|
||||
#else
|
||||
if (bCanUseHorseSkill && pkSk->dwType != SKILL_TYPE_HORSE)
|
||||
#endif
|
||||
return BATTLE_NONE;
|
||||
|
||||
if (!bCanUseHorseSkill && pkSk->dwType == SKILL_TYPE_HORSE)
|
||||
@@ -2509,18 +2491,7 @@ bool CHARACTER::UseSkill(DWORD dwVnum, LPCHARACTER pkVictim, bool bUseGrandMaste
|
||||
|
||||
// 말을 타고있지만 스킬은 사용할 수 없는 상태라면 return false
|
||||
if (false == bCanUseHorseSkill && true == IsRiding())
|
||||
#ifdef FIX_REFRESH_SKILL_COOLDOWN
|
||||
{
|
||||
const bool bToggleSkill = pkSk && IS_SET(pkSk->dwFlag, SKILL_FLAG_TOGGLE);
|
||||
const bool bToggleActive = bToggleSkill ? (dwVnum == SKILL_COMBO ? m_bComboIndex != 0 : FindAffect(dwVnum) != nullptr) : false;
|
||||
|
||||
// Allow only deactivation of already-active toggles (combo or other) while riding
|
||||
if (!bToggleActive)
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
// CSkillProto * pkSk = CSkillManager::instance().Get(dwVnum);
|
||||
sys_log(0, "%s: USE_SKILL: %d pkVictim %p", GetName(), dwVnum, get_pointer(pkVictim));
|
||||
@@ -2528,14 +2499,16 @@ bool CHARACTER::UseSkill(DWORD dwVnum, LPCHARACTER pkVictim, bool bUseGrandMaste
|
||||
if (!pkSk)
|
||||
return false;
|
||||
|
||||
#ifdef FIX_REFRESH_SKILL_COOLDOWN
|
||||
const bool bIsToggleSkill = IS_SET(pkSk->dwFlag, SKILL_FLAG_TOGGLE);
|
||||
const bool bToggleActive = bIsToggleSkill ? (dwVnum == SKILL_COMBO ? m_bComboIndex != 0 : FindAffect(dwVnum) != nullptr) : false;
|
||||
|
||||
if (bCanUseHorseSkill && pkSk->dwType != SKILL_TYPE_HORSE && !(bIsToggleSkill && bToggleActive))
|
||||
#else
|
||||
if (bCanUseHorseSkill && pkSk->dwType != SKILL_TYPE_HORSE)
|
||||
#ifdef FIX_BATTLE_INACTIVITY_TIMEOUT
|
||||
// tw1x1: POS_FIGHTING timer fix
|
||||
if (IsPC() && IS_SET(pkSk->dwFlag, SKILL_FLAG_ATTACK))
|
||||
{
|
||||
EnterCombat();
|
||||
}
|
||||
// tw1x1: end
|
||||
#endif
|
||||
|
||||
if (bCanUseHorseSkill && pkSk->dwType != SKILL_TYPE_HORSE)
|
||||
return BATTLE_NONE;
|
||||
|
||||
if (!bCanUseHorseSkill && pkSk->dwType == SKILL_TYPE_HORSE)
|
||||
@@ -2695,7 +2668,15 @@ bool CHARACTER::UseSkill(DWORD dwVnum, LPCHARACTER pkVictim, bool bUseGrandMaste
|
||||
ResetChainLightningIndex();
|
||||
AddChainLightningExcept(pkVictim);
|
||||
}
|
||||
|
||||
|
||||
#ifdef FIX_BATTLE_INACTIVITY_TIMEOUT
|
||||
// tw1x1: POS_FIGHTING timer fix
|
||||
if (IsPC() && IS_SET(pkSk->dwFlag, SKILL_FLAG_ATTACK))
|
||||
{
|
||||
EnterCombat();
|
||||
}
|
||||
// tw1x1: end
|
||||
#endif
|
||||
|
||||
if (IS_SET(pkSk->dwFlag, SKILL_FLAG_SELFONLY))
|
||||
ComputeSkill(dwVnum, this);
|
||||
|
||||
@@ -864,7 +864,11 @@ namespace quest
|
||||
ch->PointChange(POINT_SUB_SKILL, newLevel < 10 ? 0 : newLevel - MAX(ch->GetLevel(), 9));
|
||||
ch->PointChange(POINT_STAT, ((MINMAX(1, newLevel, 90) - ch->GetLevel()) * 3) + ch->GetPoint(POINT_LEVEL_STEP));
|
||||
//레벨
|
||||
#if defined(__BL_LEVEL_FIX__)
|
||||
ch->PointChange(POINT_LEVEL, newLevel - ch->GetLevel(), false, true);
|
||||
#else
|
||||
ch->PointChange(POINT_LEVEL, newLevel - ch->GetLevel());
|
||||
#endif
|
||||
//HP, SP
|
||||
ch->SetRandomHP((newLevel - 1) * number(JobInitialPoints[ch->GetJob()].hp_per_lv_begin, JobInitialPoints[ch->GetJob()].hp_per_lv_end));
|
||||
ch->SetRandomSP((newLevel - 1) * number(JobInitialPoints[ch->GetJob()].sp_per_lv_begin, JobInitialPoints[ch->GetJob()].sp_per_lv_end));
|
||||
|
||||
Reference in New Issue
Block a user