diff --git a/README.md b/README.md index c5e3ac5..09e7a90 100644 --- a/README.md +++ b/README.md @@ -23,19 +23,15 @@ It builds as it is, without external dependencies. ## πŸ“‹ Changelog ### πŸ› Bug Fixes -* **Realtime Character Level Updates:** Implemented the reversed fix (credits to Mali) for updating character level in real-time across game view and all windows (such as Guild window) for all viewing players. +* **HP/SP Value Persistence:** Fixed an issue where current HP/SP values were incorrectly affected by changes to Max HP/SP (such as stat upgrades or equipment changes). +* **GM Kill Command:** Updated the `/kill` command to properly zero out the target's HP. +* **Messenger Deletion (Offline):** Fixed an issue where a companion needed to be online for a "remove from messenger" action to complete. +* **Messenger Deletion (Cross-Channel):** Fixed an issue where the removal message was visible to both parties even if they were in different channels or cores at the time of deletion. +* **Dungeon Party Logic:** Fixed an issue where the same message would popup to all affected parties when a leader tried to kick a player or a player tried to leave a team while inside a dungeon. Includes several other update message optimizations and dungeon logic improvements regarding party kicking/leaving. ### ⬆️ Feature Improvements -* **Character position auto-reverts from ```POS_FIGHTING``` to ```POS_STANDING``` after 10 seconds of battle inactivity:** Affects the final logout countdown (from 10s to 3s) as character state updating for real-time data across server functions. Tests performed (and succeeded): - * The character takes hits from another character. - * The character hits another character. - * The character takes hits from mobs. - * The character hits mobs/stones. - * The character uses an aggressive skill to another character. - * An aggressive skill is being used on the character. - * The character uses an aggressive skill to a mob/stone, without killing the instance. - * A boss uses a skill on the character. - -All credits go to #tw1x1 for this amazing and smoothly executed fix! +* **Job-Specific Stat Resets:** Individual stats reset scrolls (Items 71103, 71104, 71105, 71106) now recover stats to their initial values based on character job instead of defaulting to 1, returning the appropriate points. Translations now dynamically display the selected stat's value. Translation for Reset all-status scroll (71002) also adjusted from printing 'to 1'. +* **Logout Interruption:** Using a skill now automatically cancels the logout countdown for both the user and the target (if applicable). +* **Auto Potion Logic:** Auto potions can now be moved within the inventory while active and are automatically disabled immediately before being dropped to the ground. diff --git a/src/common/service.h b/src/common/service.h index 97a3517..4e5c38c 100644 --- a/src/common/service.h +++ b/src/common/service.h @@ -7,6 +7,4 @@ #define __PET_SYSTEM__ #define __UDP_BLOCK__ -// #define TW1X1_TEST // tw1x1 test server features - #endif diff --git a/src/game/char.cpp b/src/game/char.cpp index a9311de..241cf97 100644 --- a/src/game/char.cpp +++ b/src/game/char.cpp @@ -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: diff --git a/src/game/char_item.cpp b/src/game/char_item.cpp index bcc9139..454f4c9 100644 --- a/src/game/char_item.cpp +++ b/src/game/char_item.cpp @@ -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()) { diff --git a/src/game/char_skill.cpp b/src/game/char_skill.cpp index 13e96c7..2617237 100644 --- a/src/game/char_skill.cpp +++ b/src/game/char_skill.cpp @@ -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; } diff --git a/src/game/cmd_gm.cpp b/src/game/cmd_gm.cpp index a5f55f7..ba8959c 100644 --- a/src/game/cmd_gm.cpp +++ b/src/game/cmd_gm.cpp @@ -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(); } diff --git a/src/game/input_login.cpp b/src/game/input_login.cpp index 57e3d15..9ac37e1 100644 --- a/src/game/input_login.cpp +++ b/src/game/input_login.cpp @@ -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); diff --git a/src/game/input_main.cpp b/src/game/input_main.cpp index 2913d3a..6942fbc 100644 --- a/src/game/input_main.cpp +++ b/src/game/input_main.cpp @@ -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) diff --git a/src/game/input_p2p.cpp b/src/game/input_p2p.cpp index f341c64..1c50a78 100644 --- a/src/game/input_p2p.cpp +++ b/src/game/input_p2p.cpp @@ -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) diff --git a/src/game/messenger_manager.cpp b/src/game/messenger_manager.cpp index 93d92d4..af90199 100644 --- a/src/game/messenger_manager.cpp +++ b/src/game/messenger_manager.cpp @@ -409,13 +409,13 @@ void MessengerManager::EraseRequestsForAccount(keyA account) std::vector 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 } /* λ³΅μ‚¬ν•œ 데이타 μ‚­μ œ */ diff --git a/src/game/messenger_manager.h b/src/game/messenger_manager.h index cafccf9..ca794be 100644 --- a/src/game/messenger_manager.h +++ b/src/game/messenger_manager.h @@ -34,8 +34,10 @@ class MessengerManager : public singleton 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);