MR-3: Bunch of fixes

This commit is contained in:
Mind Rapist
2025-12-25 08:45:03 +02:00
parent b2931f0f7d
commit a91d49f440
11 changed files with 200 additions and 77 deletions

View File

@@ -7,6 +7,4 @@
#define __PET_SYSTEM__
#define __UDP_BLOCK__
// #define TW1X1_TEST // tw1x1 test server features
#endif

View File

@@ -114,6 +114,9 @@ CHARACTER::CHARACTER()
m_stateIdle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateIdle, &CHARACTER::EndStateEmpty);
m_stateMove.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateMove, &CHARACTER::EndStateEmpty);
m_stateBattle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateBattle, &CHARACTER::EndStateEmpty);
#ifdef FIX_POS_SYNC
m_stateSyncing.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateSyncing, &CHARACTER::EndStateEmpty);
#endif
Initialize();
}
@@ -1802,9 +1805,9 @@ void CHARACTER::SetPlayerProto(const TPlayerTable * t)
ComputePoints();
SetHP(GetMaxHP());
SetSP(GetMaxSP());
SetStamina(GetMaxStamina());
SetHP(t->hp);
SetSP(t->sp);
SetStamina(t->stamina);
//GM일때 보호모드
if (!test_server)
@@ -2334,21 +2337,23 @@ void CHARACTER::ComputePoints()
// 기본 HP/SP 설정
if (iMaxHP != GetMaxHP())
{
SetRealPoint(POINT_MAX_HP, iMaxHP); // 기본HP를 RealPoint에 저장해 놓는다.
}
PointChange(POINT_MAX_HP, 0);
if (iMaxSP != GetMaxSP())
{
SetRealPoint(POINT_MAX_SP, iMaxSP); // 기본SP를 RealPoint에 저장해 놓는다.
}
PointChange(POINT_MAX_SP, 0);
SetMaxStamina(iMaxStamina);
// MR-3: HP/SP Fixes
int iCurHP = GetHP();
int iCurSP = GetSP();
// MR-3: -- END OF -- HP/SP Fixes
m_pointsInstant.dwImmuneFlag = 0;
for (int i = 0 ; i < WEAR_MAX_NUM; i++)
@@ -2386,18 +2391,23 @@ void CHARACTER::ComputePoints()
PointChange(POINT_SP, GetMaxSP() - GetSP());
ComputeSkillPoints();
RefreshAffect();
CPetSystem* pPetSystem = GetPetSystem();
if (NULL != pPetSystem)
{
pPetSystem->RefreshBuff();
}
for (TMapBuffOnAttrs::iterator it = m_map_buff_on_attrs.begin(); it != m_map_buff_on_attrs.end(); it++)
// MR-3: HP/SP Fixes
if (IsPC())
{
it->second->GiveAllAttributes();
CPetSystem * pPetSystem = GetPetSystem();
if (pPetSystem)
pPetSystem->RefreshBuff();
// @Fixed Hp/Mp mount/unmount
if (GetHP() != iCurHP)
SetPoint(POINT_HP, std::min(iCurHP, GetMaxHP()));
if (GetSP() != iCurSP)
SetPoint(POINT_SP, std::min(iCurSP, GetMaxSP()));
}
// MR-3: -- END OF -- HP/SP Fixes
UpdatePacket();
}
@@ -3299,13 +3309,22 @@ void CHARACTER::PointChange(BYTE type, int amount, bool bAmount, bool bBroadcast
//SetMaxHP(GetMaxHP() + amount);
// 최대 생명력 = (기본 최대 생명력 + 추가) * 최대생명력%
int i = GetHP();
int hp = GetRealPoint(POINT_MAX_HP);
int add_hp = MIN(3500, hp * GetPoint(POINT_MAX_HP_PCT) / 100);
add_hp += GetPoint(POINT_MAX_HP);
add_hp += GetPoint(POINT_PARTY_TANKER_BONUS);
SetMaxHP(hp + add_hp);
// MR-3: HP/SP Fixes
if (GetHP() > GetMaxHP())
SetPoint(POINT_HP, GetMaxHP());
else
SetPoint(POINT_HP, i);
// MR-3: -- END OF -- HP/SP Fixes
val = GetMaxHP();
}
break;
@@ -3316,13 +3335,22 @@ void CHARACTER::PointChange(BYTE type, int amount, bool bAmount, bool bBroadcast
//SetMaxSP(GetMaxSP() + amount);
// 최대 정신력 = (기본 최대 정신력 + 추가) * 최대정신력%
int i = GetSP();
int sp = GetRealPoint(POINT_MAX_SP);
int add_sp = MIN(800, sp * GetPoint(POINT_MAX_SP_PCT) / 100);
add_sp += GetPoint(POINT_MAX_SP);
add_sp += GetPoint(POINT_PARTY_SKILL_MASTER_BONUS);
SetMaxSP(sp + add_sp);
// MR-3: HP/SP Fixes
if (GetSP() > GetMaxSP())
SetPoint(POINT_SP, GetMaxSP());
else
SetPoint(POINT_SP, i);
// MR-3: -- END OF -- HP/SP Fixes
val = GetMaxSP();
}
break;
@@ -3720,12 +3748,27 @@ void CHARACTER::ApplyPoint(BYTE bApplyType, int iVal)
// END_OF_SKILL_DAMAGE_BONUS
break;
// MR-3: HP/SP Fixes
case APPLY_MAX_HP:
case APPLY_MAX_HP_PCT:
{
int i = GetMaxHP(); if(i == 0) break;
int curr = GetHP();
PointChange(aApplyInfo[bApplyType].bPointType, iVal);
}
break;
case APPLY_MAX_SP:
case APPLY_MAX_SP_PCT:
{
int i = GetMaxSP(); if(i == 0) break;
PointChange(aApplyInfo[bApplyType].bPointType, iVal);
}
break;
// MR-3: -- END OF -- HP/SP Fixes
case APPLY_STR:
case APPLY_DEX:
case APPLY_MAX_HP:
case APPLY_MAX_SP:
case APPLY_MAX_HP_PCT:
case APPLY_MAX_SP_PCT:
case APPLY_ATT_SPEED:
case APPLY_MOV_SPEED:
case APPLY_CAST_SPEED:

View File

@@ -4006,7 +4006,9 @@ bool CHARACTER::UseItemEx(LPITEM item, TItemPos DestCell)
AddAffect( type, bonus, 4, item->GetID(), INFINITE_AFFECT_DURATION, 0, true, false);
item->Lock(true);
// MR-3: Active autopotion unlock
//item->Lock(true);
// MR-3: -- END OF -- Active autopotion unlock
item->SetSocket(0, true);
AutoRecoveryItemProcess( type );
@@ -4048,7 +4050,9 @@ bool CHARACTER::UseItemEx(LPITEM item, TItemPos DestCell)
AddAffect( type, bonus, 4, item->GetID(), INFINITE_AFFECT_DURATION, 0, true, false);
item->Lock(true);
// MR-3: Active autopotion unlock
//item->Lock(true);
// MR-3: -- END OF -- Active autopotion unlock
item->SetSocket(0, true);
AutoRecoveryItemProcess( type );
@@ -5377,6 +5381,25 @@ bool CHARACTER::DropItem(TItemPos Cell, BYTE bCount)
SyncQuickslot(QUICKSLOT_TYPE_ITEM, Cell.cell, 255); // Quickslot 에서 지움
LPITEM pkItemToDrop;
// MR-3: Auto-deactivate auto potions before dropping
switch (item->GetVnum())
{
case ITEM_AUTO_HP_RECOVERY_S:
case ITEM_AUTO_HP_RECOVERY_M:
case ITEM_AUTO_HP_RECOVERY_L:
case ITEM_AUTO_HP_RECOVERY_X:
case ITEM_AUTO_SP_RECOVERY_S:
case ITEM_AUTO_SP_RECOVERY_M:
case ITEM_AUTO_SP_RECOVERY_L:
case ITEM_AUTO_SP_RECOVERY_X:
if (item->GetSocket(0) == 1)
item->SetSocket(0, 0);
break;
default:
break;
}
// MR-3: -- END OF -- Auto-deactivate auto potions before dropping
if (bCount == item->GetCount())
{

View File

@@ -2524,6 +2524,15 @@ bool CHARACTER::UseSkill(DWORD dwVnum, LPCHARACTER pkVictim, bool bUseGrandMaste
// DASH 상태의 탄환격은 공격기술
ComputeSkill(dwVnum, pkVictim);
RemoveAffect(dwVnum);
// MR-3: Cancel logout on use skill
if (m_pkTimedEvent)
{
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("취소 되었습니다."));
event_cancel(&m_pkTimedEvent);
}
// MR-3: -- END OF -- Cancel logout on use skill
return true;
}
}
@@ -2542,6 +2551,14 @@ bool CHARACTER::UseSkill(DWORD dwVnum, LPCHARACTER pkVictim, bool bUseGrandMaste
// Toggle 할 때는 SP를 쓰지 않음 (SelfOnly로 구분)
if ((0 != pkSk->dwAffectFlag || pkSk->dwVnum == SKILL_MUYEONG) && (pkSk->dwFlag & SKILL_FLAG_TOGGLE) && RemoveAffect(pkSk->dwVnum))
{
// MR-3: Cancel logout on use skill
if (m_pkTimedEvent)
{
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("취소 되었습니다."));
event_cancel(&m_pkTimedEvent);
}
// MR-3: -- END OF -- Cancel logout on use skill
return true;
}
@@ -2653,6 +2670,14 @@ bool CHARACTER::UseSkill(DWORD dwVnum, LPCHARACTER pkVictim, bool bUseGrandMaste
// prevent POS_FIGHTING from expiring when skills deal 0 damage (miss, block, imun, etc.)
UpdateLastCombatTime();
EnterCombat();
// MR-3: Cancel logout on use skill
if (pkVictim->m_pkTimedEvent)
{
pkVictim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("취소 되었습니다."));
event_cancel(&pkVictim->m_pkTimedEvent);
}
// MR-3: -- END OF -- Cancel logout on use skill
}
// tw1x1: end
@@ -2667,6 +2692,14 @@ bool CHARACTER::UseSkill(DWORD dwVnum, LPCHARACTER pkVictim, bool bUseGrandMaste
m_dwLastSkillTime = get_dword_time();
// MR-3: Cancel logout on use skill
if (m_pkTimedEvent)
{
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("취소 되었습니다."));
event_cancel(&m_pkTimedEvent);
}
// MR-3: -- END OF -- Cancel logout on use skill
return true;
}

View File

@@ -1358,6 +1358,9 @@ ACMD(do_kill)
return;
}
// MR-3: Empty HP on kill
tch->PointChange(POINT_HP, -tch->GetHP());
// MR-3: -- END OF -- Empty HP on kill
tch->Dead();
}

View File

@@ -585,6 +585,7 @@ void CInputLogin::Entergame(LPDESC d, const char * data)
ch->Show(ch->GetMapIndex(), pos.x, pos.y, pos.z);
SECTREE_MANAGER::instance().SendNPCPosition(ch);
ch->ReviveInvisible(5);
d->SetPhase(PHASE_GAME);

View File

@@ -1034,8 +1034,11 @@ int CInputMain::Messenger(LPCHARACTER ch, const char* c_pData, size_t uiBytes)
char char_name[CHARACTER_NAME_MAX_LEN + 1];
strlcpy(char_name, c_pData, sizeof(char_name));
// MR-3: Remove from messenger Fix
MessengerManager::instance().RemoveFromList(ch->GetName(), char_name);
MessengerManager::instance().RemoveFromList(char_name, ch->GetName()); // friend removed from companion too.
MessengerManager::instance().RemoveFromList(char_name, ch->GetName(), false); // friend removed from companion too.
// MR-3: -- END OF -- Remove from messenger Fix
}
return CHARACTER_NAME_MAX_LEN;
@@ -2359,35 +2362,41 @@ void CInputMain::PartyRemove(LPCHARACTER ch, const char* c_pData)
return;
}
if (ch->GetDungeon())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 던전 안에서는 파티에서 추방할 수 없습니다."));
return;
}
// MR-3: Fix party removal chat messages and improved dungeon logic
TPacketCGPartyRemove* p = (TPacketCGPartyRemove*) c_pData;
if (!ch->GetParty())
return;
LPPARTY pParty = ch->GetParty();
if (pParty->GetLeaderPID() == ch->GetPlayerID())
{
if (ch->GetDungeon())
// leader can remove any member
if (p->pid == ch->GetPlayerID() || pParty->GetMemberCount() == 2)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 던젼내에서는 파티원을 추방할 수 없습니다."));
}
else
{
// leader can remove any member
if (p->pid == ch->GetPlayerID() || pParty->GetMemberCount() == 2)
if (ch->GetDungeon())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 던전 안에서는 파티에서 추방할 수 없습니다."));
return;
}
else
{
// party disband
CPartyManager::instance().DeleteParty(pParty);
}
}
else
{
if (ch->GetDungeon())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 던젼내에서는 파티원을 추방할 수 없습니다."));
return;
}
else
{
LPCHARACTER B = CHARACTER_MANAGER::instance().FindByPID(p->pid);
if (B)
{
//pParty->SendPartyRemoveOneToAll(B);
@@ -2395,6 +2404,7 @@ void CInputMain::PartyRemove(LPCHARACTER ch, const char* c_pData)
//pParty->Unlink(B);
//CPartyManager::instance().SetPartyMember(B->GetPlayerID(), NULL);
}
pParty->Quit(p->pid);
}
}
@@ -2404,17 +2414,26 @@ void CInputMain::PartyRemove(LPCHARACTER ch, const char* c_pData)
// otherwise, only remove itself
if (p->pid == ch->GetPlayerID())
{
if (ch->GetDungeon())
if (pParty->GetMemberCount() == 2)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 던젼내에서는 파티를 나갈 수 없습니다."));
}
else
{
if (pParty->GetMemberCount() == 2)
if (ch->GetDungeon())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 던전 안에서는 파티에서 추방할 수 없습니다."));
return;
}
else
{
// party disband
CPartyManager::instance().DeleteParty(pParty);
}
}
else
{
if (ch->GetDungeon())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 던젼내에서는 파티를 나갈 수 없습니다."));
return;
}
else
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티에서 나가셨습니다."));
@@ -2430,6 +2449,7 @@ void CInputMain::PartyRemove(LPCHARACTER ch, const char* c_pData)
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 다른 파티원을 탈퇴시킬 수 없습니다."));
}
}
// MR-3: -- END OF -- Fix party removal chat messages and improved dungeon logic
}
void CInputMain::AnswerMakeGuild(LPCHARACTER ch, const char* c_pData)

View File

@@ -325,8 +325,9 @@ void CInputP2P::MessengerRemove(const char * c_pData)
deletee->GetDesc()->Packet(p->szAccount, strlen(p->szAccount));
}
// MR-3: Remove from messenger Fix
MessengerManager::instance().__RemoveFromList(p->szAccount, p->szCompanion);
MessengerManager::instance().__RemoveFromList(p->szCompanion, p->szAccount, false);
// MR-3: -- END OF -- Remove from messenger Fix
}
void CInputP2P::FindPosition(LPDESC d, const char* c_pData)

View File

@@ -409,13 +409,13 @@ void MessengerManager::EraseRequestsForAccount(keyA account)
std::vector<DWORD> toRemove;
auto itFrom = m_map_requestsFrom.find(dw);
// auto itFrom = m_map_requestsFrom.find(dw);
if (itFrom != m_map_requestsFrom.end())
{
for (DWORD c : itFrom->second)
toRemove.push_back(c);
}
// if (itFrom != m_map_requestsFrom.end())
// {
// for (DWORD c : itFrom->second)
// toRemove.push_back(c);
// }
auto itTo = m_map_requestsTo.find(dw);
@@ -510,19 +510,14 @@ void MessengerManager::AddToList(MessengerManager::keyA account, MessengerManage
P2P_MANAGER::instance().Send(&p2ppck, sizeof(TPacketGGMessenger));
}
void MessengerManager::__RemoveFromList(MessengerManager::keyA account, MessengerManager::keyA companion, bool isRequester)
// MR-3: Remove from messenger Fix
void MessengerManager::__RemoveFromList(MessengerManager::keyA account, MessengerManager::keyA companion)
{
m_Relation[account].erase(companion);
m_InverseRelation[companion].erase(account);
m_Relation[companion].erase(account);
m_InverseRelation[account].erase(companion);
LPCHARACTER ch = CHARACTER_MANAGER::instance().FindPC(account.c_str());
LPDESC d = ch ? ch->GetDesc() : NULL;
if (d && isRequester)
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<메신져> %s 님을 메신저에서 삭제하였습니다."), companion.c_str());
LPCHARACTER tch = CHARACTER_MANAGER::Instance().FindPC(companion.c_str());
if (tch && tch->GetDesc())
@@ -539,6 +534,7 @@ void MessengerManager::__RemoveFromList(MessengerManager::keyA account, Messenge
tch->GetDesc()->Packet(account.c_str(), account.size());
}
}
// MR-3: -- END OF -- Remove from messenger Fix
bool MessengerManager::IsInList(MessengerManager::keyA account, MessengerManager::keyA companion) // Fix
{
@@ -551,7 +547,7 @@ bool MessengerManager::IsInList(MessengerManager::keyA account, MessengerManager
return m_Relation[account].find(companion) != m_Relation[account].end();
}
void MessengerManager::RemoveFromList(MessengerManager::keyA account, MessengerManager::keyA companion)
void MessengerManager::RemoveFromList(MessengerManager::keyA account, MessengerManager::keyA companion, bool isRequester)
{
if (companion.empty())
return;
@@ -559,9 +555,6 @@ void MessengerManager::RemoveFromList(MessengerManager::keyA account, MessengerM
if (companion.size() == 0)
return;
if (!IsInList(account, companion)) // Fix
return;
DBManager::instance().EscapeString(__account, sizeof(__account), account.c_str(), account.size());
DBManager::instance().EscapeString(__companion, sizeof(__companion), companion.c_str(), companion.size());
@@ -574,6 +567,14 @@ void MessengerManager::RemoveFromList(MessengerManager::keyA account, MessengerM
DBManager::instance().Query("DELETE FROM messenger_list%s WHERE (account='%s' AND companion = '%s') OR (account = '%s' AND companion = '%s')",
get_table_postfix(), account.c_str(), companion.c_str(), companion.c_str(), account.c_str());
// MR-3: Remove from messenger Fix
LPCHARACTER ch = CHARACTER_MANAGER::instance().FindPC(account.c_str());
LPDESC d = ch ? ch->GetDesc() : NULL;
if (d && isRequester)
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<메신져> %s 님을 메신저에서 삭제하였습니다."), companion.c_str());
// MR-3: -- END OF -- Remove from messenger Fix
__RemoveFromList(account, companion);
TPacketGGMessenger p2ppck;
@@ -602,8 +603,10 @@ void MessengerManager::RemoveAllList(keyA account)
iter != company.end();
iter++ )
{
this->RemoveFromList(account, *iter);
this->RemoveFromList(*iter, account);
// MR-3: Remove from messenger Fix
this->RemoveFromList(account, *iter, false);
this->RemoveFromList(*iter, account, false);
// MR-3: -- END OF -- Remove from messenger Fix
}
/* 복사한 데이타 삭제 */

View File

@@ -34,8 +34,10 @@ class MessengerManager : public singleton<MessengerManager>
void __AddToList(keyA account, keyA companion, bool isRequester = true); // 실제 m_Relation, m_InverseRelation 수정하는 메소드
void AddToList(keyA account, keyA companion);
void __RemoveFromList(keyA account, keyA companion, bool isRequester = true); // 실제 m_Relation, m_InverseRelation 수정하는 메소드
void RemoveFromList(keyA account, keyA companion);
// MR-3: Remove from messenger Fix
void __RemoveFromList(keyA account, keyA companion); // 실제 m_Relation, m_InverseRelation 수정하는 메소드
void RemoveFromList(keyA account, keyA companion, bool isRequester = true);
// MR-3: -- END OF -- Remove from messenger Fix
void RemoveAllList(keyA account);