Honorable Member Mali 41754 Posted May 12, 2018 Honorable Member Share Posted May 12, 2018 M2 Download Center This is the hidden content, please Sign In or Sign Up ( Internal ) This is the hidden content, please Sign In or Sign Up ( GitHub ) Spoiler 153 1 1 1 3 1 1 33 1 3 77 Link to comment Share on other sites More sharing options...
Shang 369 Posted May 12, 2018 Share Posted May 12, 2018 In official servers the party is the same in all channels, looking your code without touching the db src... you can delete Official from the title. 1 Link to comment Share on other sites More sharing options...
Honorable Member Mali 41754 Posted May 12, 2018 Author Honorable Member Share Posted May 12, 2018 6 minutes ago, Shang said: In official servers the party is the same in all channels, looking your code without touching the db src... you can delete Official from the title. What? Link to comment Share on other sites More sharing options...
Premium Galet 509 Posted May 12, 2018 Premium Share Posted May 12, 2018 Thanks for share dude ! By the way, he means that your code is not like official as it's not reversed. He's just asking for a clarification in the title, such as "Party Update like Official" or just to remove "Official" in the title as it's just a recreation and not the official code. Link to comment Share on other sites More sharing options...
Forum Moderator Raylee 656 Posted May 12, 2018 Forum Moderator Share Posted May 12, 2018 Great release Thank you Best regards Raylee Link to comment Share on other sites More sharing options...
Legend 186 Posted May 12, 2018 Share Posted May 12, 2018 Thanks for the share, but there is a bug with the system if you have party and you disconnect from both characters after when you login and one of the two characters are offline shows him online. Link to comment Share on other sites More sharing options...
NEFFEX 2 Posted May 13, 2018 Share Posted May 13, 2018 Nice, thank you Link to comment Share on other sites More sharing options...
Honorable Member Mali 41754 Posted May 13, 2018 Author Honorable Member Share Posted May 13, 2018 #Update: Fixed offline/online problem(party.cpp->SendPartyJoinAllToOne, uiparty.py->AddPartyMember) Code improvement(party.cpp->P2PJoin) 2 Link to comment Share on other sites More sharing options...
Bot Metin2 Dev 4873 Posted May 15, 2018 Bot Share Posted May 15, 2018 Thanks for the release. I found a bug: when you are at a party and you teleport to a map whose core is different from the map core of the other member of the party, it will show the member as [Offline], that should not happen. Can you look at it, please? : D Regarding what @Shang says, he means that in the official server, when you create a party, that party is created in all the channels, that is, if you change the channel, the party will be in the channel that was created and in any channel that you change, but still without putting your release, at least in the majority of public sources this does not happen, I suppose the part of creating the party in all the channels at the same time was a recent update of gameforge. So this is not a problem, since it is simply to create the party manually on all channels. xD Sorry for my bad English. 1 Link to comment Share on other sites More sharing options...
zeimpekis9 68 Posted May 17, 2018 Share Posted May 17, 2018 On 5/15/2018 at 10:50 PM, WLsj24 said: Thanks for the release. I found a bug: when you are at a party and you teleport to a map whose core is different from the map core of the other member of the party, it will show the member as [Offline], that should not happen. Can you look at it, please? : D Regarding what @Shang says, he means that in the official server, when you create a party, that party is created in all the channels, that is, if you change the channel, the party will be in the channel that was created and in any channel that you change, but still without putting your release, at least in the majority of public sources this does not happen, I suppose the part of creating the party in all the channels at the same time was a recent update of gameforge. So this is not a problem, since it is simply to create the party manually on all channels. xD Sorry for my bad English. It is working 100% right now? Link to comment Share on other sites More sharing options...
Bot Metin2 Dev 4873 Posted May 17, 2018 Bot Share Posted May 17, 2018 3 hours ago, zeimpekis9 said: It is working 100% right now? Yes, the only problem is that if "Player1" is in Pyugmoo and "Player2" is in "Spider Dungeon", that is, the members of the party are in different core, (you know, cities are usually in the core1, and maps like Yongbi are usually in the core2) because in that case it will show the one in a different cores as [Offline] (even if both members are online) in the party. If @Mali61 fix that, then one could already speak of a functional version without bugs. 1 Link to comment Share on other sites More sharing options...
Honorable Member Mali 41754 Posted May 17, 2018 Author Honorable Member Share Posted May 17, 2018 2 hours ago, WLsj24 said: Yes, the only problem is that if "Player1" is in Pyugmoo and "Player2" is in "Spider Dungeon", that is, the members of the party are in different core, (you know, cities are usually in the core1, and maps like Yongbi are usually in the core2) because in that case it will show the one in a different cores as [Offline] (even if both members are online) in the party. If @Mali61 fix that, then one could already speak of a functional version without bugs. Please wait weekend I'm busy 3 Link to comment Share on other sites More sharing options...
zeimpekis9 68 Posted May 20, 2018 Share Posted May 20, 2018 On 5/17/2018 at 8:46 PM, Mali61 said: Please wait weekend I'm busy So, did you fixed it? Link to comment Share on other sites More sharing options...
Honorable Member Mali 41754 Posted May 20, 2018 Author Honorable Member Share Posted May 20, 2018 5 hours ago, zeimpekis9 said: So, did you fixed it? Yeah now party will create in all channels but still has some problem with online/offline problem.I don't have enough time but don't worry I will fix it. 1 Link to comment Share on other sites More sharing options...
Premium North 1172 Posted May 21, 2018 Premium Share Posted May 21, 2018 15 hours ago, Mali61 said: Yeah now party will create in all channels but still has some problem with online/offline problem.I don't have enough time but don't worry I will fix it. I don't even know why you are taking orders from random people but nice work thanks for the relase. Link to comment Share on other sites More sharing options...
zeimpekis9 68 Posted May 21, 2018 Share Posted May 21, 2018 11 minutes ago, Fleon said: I don't even know why you are taking orders from random people but nice work thanks for the relase. 11 minutes ago, Fleon said: I don't even know why you are taking orders from random people but nice work thanks for the relase. he is not taking orders. He released a system. We infrom him about the bugs of the system, and we just asked IF he can fix it. Why everyone here is so rude? I dont understand you. You should learn to help RANDOM people and to flame all the time. FFS. Link to comment Share on other sites More sharing options...
Premium North 1172 Posted May 21, 2018 Premium Share Posted May 21, 2018 50 minutes ago, zeimpekis9 said: he is not taking orders. He released a system. We infrom him about the bugs of the system, and we just asked IF he can fix it. Why everyone here is so rude? I dont understand you. You should learn to help RANDOM people and to flame all the time. FFS. Lul. You are not informing him when you ask "So, did you fix it?" but instead it sounds like a request from somebody who should only be grateful, if you want to help then go for a pull request implementing the feature/bugfix on your own. I've been helping random people way too much, that's why I understood that random people usually don't deserve anything :]. It's git tho, if you want to know if he updated the code then check the commits instead of asking here, you know. 2 Link to comment Share on other sites More sharing options...
BeHappy4Ever 247 Posted May 21, 2018 Share Posted May 21, 2018 2 hours ago, zeimpekis9 said: he is not taking orders. He released a system. We infrom him about the bugs of the system, and we just asked IF he can fix it. Why everyone here is so rude? I dont understand you. You should learn to help RANDOM people and to flame all the time. FFS. Ηelping random people is like feeding a snake .. Link to comment Share on other sites More sharing options...
zeimpekis9 68 Posted May 21, 2018 Share Posted May 21, 2018 2 hours ago, Fleon said: Lul. You are not informing him when you ask "So, did you fix it?" but instead it sounds like a request from somebody who should only be grateful, if you want to help then go for a pull request implementing the feature/bugfix on your own. I've been helping random people way too much, that's why I understood that random people usually don't deserve anything :]. It's git tho, if you want to know if he updated the code then check the commits instead of asking here, you know. 12 minutes ago, BeHappy4Ever said: Ηelping random people is like feeding a snake .. Whatever. You are so wrong and you dont understand. I will not explain to you anymore. Link to comment Share on other sites More sharing options...
BeHappy4Ever 247 Posted May 21, 2018 Share Posted May 21, 2018 3 minutes ago, zeimpekis9 said: Whatever. You are so wrong and you dont understand. I will not explain to you anymore. Okay man... Tρεις και παρ'τα αρχιδια μου!XX Link to comment Share on other sites More sharing options...
zeimpekis9 68 Posted May 21, 2018 Share Posted May 21, 2018 6 minutes ago, BeHappy4Ever said: Okay man... Tρεις και παρ'τα αρχιδια μου!XX Δεν αναφερόμουν σε σένα αλλά εντάξει. Link to comment Share on other sites More sharing options...
Forum Moderator Raylee 656 Posted May 21, 2018 Forum Moderator Share Posted May 21, 2018 vor 1 Stunde schrieb BeHappy4Ever: Okay man... Tρεις και παρ'τα αρχιδια μου!XX vor 1 Stunde schrieb zeimpekis9: Δεν αναφερόμουν σε σένα αλλά εντάξει. ENGLISH GUYS!!!! Rules §1 Language (1.1) Language The language in this board is english. If you want to post something in your own language always add an english translation. The only exception for this rule is this section: Private Servers Read the rules guys -.- Best regards Raylee Link to comment Share on other sites More sharing options...
dharokko 7 Posted May 22, 2018 Share Posted May 22, 2018 (edited) Am 12.5.2018 um 21:53 schrieb Mali61: This is the hidden content, please Sign In or Sign Up can you create a code methode for vs 2008? The src db part is just for 2011. ClientManager.cpp: In member function 'void CClientManager::SendPartyOnSetup(CPeer*)': ClientManager.cpp:424: error: a function-definition is not allowed here before ':' token ClientManager.cpp:424: error: expected primary-expression before ')' token ClientManager.cpp:424: error: expected `;' before ')' token ClientManager.cpp:426: error: 'channels' was not declared in this scope Spoiler #ifdef BL_PARTY_UPDATE for (auto channels : {1,2,3,4,99}) { TPartyMap & pm = m_map_pkChannelParty[channels]; for (itertype(pm) it_party = pm.begin(); it_party != pm.end(); ++it_party) { sys_log(0, "PARTY SendPartyOnSetup Party [%u]", it_party->first); pkPeer->EncodeHeader(HEADER_DG_PARTY_CREATE, 0, sizeof(TPacketPartyCreate)); pkPeer->Encode(&it_party->first, sizeof(DWORD)); for (itertype(it_party->second) it_member = it_party->second.begin(); it_member != it_party->second.end(); ++it_member) { sys_log(0, "PARTY SendPartyOnSetup Party [%u] Member [%u]", it_party->first, it_member->first); pkPeer->EncodeHeader(HEADER_DG_PARTY_ADD, 0, sizeof(TPacketPartyAdd)); pkPeer->Encode(&it_party->first, sizeof(DWORD)); pkPeer->Encode(&it_member->first, sizeof(DWORD)); pkPeer->Encode(&it_member->second.bRole, sizeof(BYTE)); pkPeer->EncodeHeader(HEADER_DG_PARTY_SET_MEMBER_LEVEL, 0, sizeof(TPacketPartySetMemberLevel)); pkPeer->Encode(&it_party->first, sizeof(DWORD)); pkPeer->Encode(&it_member->first, sizeof(DWORD)); pkPeer->Encode(&it_member->second.bLevel, sizeof(BYTE)); } } } #else ClientManagerParty.cpp:8: error: function definition does not declare parameters ClientManagerParty.cpp: In member function 'void CClientManager::QUERY_PARTY_CREATE(CPeer*, TPacketPartyCreate*)': ClientManagerParty.cpp:13: error: a function-definition is not allowed here before ':' token ClientManagerParty.cpp:239: error: expected primary-expression at end of input ClientManagerParty.cpp:239: error: expected `;' at end of input ClientManagerParty.cpp:239: error: expected primary-expression at end of input ClientManagerParty.cpp:239: error: expected `)' at end of input ClientManagerParty.cpp:239: error: expected statement at end of input ClientManagerParty.cpp:239: error: expected `}' at end of input Spoiler #include "stdafx.h" #include "ClientManager.h" #include "Config.h" #include "DBManager.h" #include "QID.h" #ifdef BL_PARTY_UPDATE std::vector <DWORD> channel_info {1,2,3,4,99}; #endif void CClientManager::QUERY_PARTY_CREATE(CPeer* peer, TPacketPartyCreate* p) { #ifdef BL_PARTY_UPDATE for (auto channels : channel_info) { TPartyMap & pm = m_map_pkChannelParty[channels]; if (pm.find(p->dwLeaderPID) == pm.end()) { pm.insert(make_pair(p->dwLeaderPID, TPartyMember())); ForwardPacket(HEADER_DG_PARTY_CREATE, p, sizeof(TPacketPartyCreate), channels, peer); sys_log(0, "PARTY Create [%lu]", p->dwLeaderPID); } } #else TPartyMap & pm = m_map_pkChannelParty[peer->GetChannel()]; if (pm.find(p->dwLeaderPID) == pm.end()) { pm.insert(make_pair(p->dwLeaderPID, TPartyMember())); ForwardPacket(HEADER_DG_PARTY_CREATE, p, sizeof(TPacketPartyCreate), peer->GetChannel(), peer); sys_log(0, "PARTY Create [%lu]", p->dwLeaderPID); } else { sys_err("PARTY Create - Already exists [%lu]", p->dwLeaderPID); } #endif } void CClientManager::QUERY_PARTY_DELETE(CPeer* peer, TPacketPartyDelete* p) { #ifdef BL_PARTY_UPDATE for (auto channels : channel_info) { TPartyMap& pm = m_map_pkChannelParty[channels]; itertype(pm) it = pm.find(p->dwLeaderPID); if (it == pm.end()) return; pm.erase(it); ForwardPacket(HEADER_DG_PARTY_DELETE, p, sizeof(TPacketPartyDelete), channels, peer); } #else TPartyMap& pm = m_map_pkChannelParty[peer->GetChannel()]; itertype(pm) it = pm.find(p->dwLeaderPID); if (it == pm.end()) { sys_err("PARTY Delete - Non exists [%lu]", p->dwLeaderPID); return; } pm.erase(it); ForwardPacket(HEADER_DG_PARTY_DELETE, p, sizeof(TPacketPartyDelete), peer->GetChannel(), peer); #endif sys_log(0, "PARTY Delete [%lu]", p->dwLeaderPID); } void CClientManager::QUERY_PARTY_ADD(CPeer* peer, TPacketPartyAdd* p) { #ifdef BL_PARTY_UPDATE for (auto channels : channel_info) { TPartyMap & pm = m_map_pkChannelParty[channels]; itertype(pm) it = pm.find(p->dwLeaderPID); if (it == pm.end()) return; if (it->second.find(p->dwPID) == it->second.end()) { it->second.insert(std::make_pair(p->dwPID, TPartyInfo())); ForwardPacket(HEADER_DG_PARTY_ADD, p, sizeof(TPacketPartyAdd), channels, peer); sys_log(0, "PARTY Add [%lu] to [%lu]", p->dwPID, p->dwLeaderPID); } } #else TPartyMap & pm = m_map_pkChannelParty[peer->GetChannel()]; itertype(pm) it = pm.find(p->dwLeaderPID); if (it == pm.end()) { sys_err("PARTY Add - Non exists [%lu]", p->dwLeaderPID); return; } if (it->second.find(p->dwPID) == it->second.end()) { it->second.insert(std::make_pair(p->dwPID, TPartyInfo())); ForwardPacket(HEADER_DG_PARTY_ADD, p, sizeof(TPacketPartyAdd), peer->GetChannel(), peer); sys_log(0, "PARTY Add [%lu] to [%lu]", p->dwPID, p->dwLeaderPID); } else sys_err("PARTY Add - Already [%lu] in party [%lu]", p->dwPID, p->dwLeaderPID); #endif } void CClientManager::QUERY_PARTY_REMOVE(CPeer* peer, TPacketPartyRemove* p) { #ifdef BL_PARTY_UPDATE for (auto channels : channel_info) { TPartyMap & pm = m_map_pkChannelParty[channels]; itertype(pm) it = pm.find(p->dwLeaderPID); if (it == pm.end()) return; itertype(it->second) pit = it->second.find(p->dwPID); if (pit != it->second.end()) { it->second.erase(pit); ForwardPacket(HEADER_DG_PARTY_REMOVE, p, sizeof(TPacketPartyRemove), channels, peer); sys_log(0, "PARTY Remove [%lu] to [%lu]", p->dwPID, p->dwLeaderPID); } } #else TPartyMap & pm = m_map_pkChannelParty[peer->GetChannel()]; itertype(pm) it = pm.find(p->dwLeaderPID); if (it == pm.end()) { sys_err("PARTY Remove - Non exists [%lu] cannot remove [%lu]",p->dwLeaderPID, p->dwPID); return; } itertype(it->second) pit = it->second.find(p->dwPID); if (pit != it->second.end()) { it->second.erase(pit); ForwardPacket(HEADER_DG_PARTY_REMOVE, p, sizeof(TPacketPartyRemove), peer->GetChannel(), peer); sys_log(0, "PARTY Remove [%lu] to [%lu]", p->dwPID, p->dwLeaderPID); } else sys_err("PARTY Remove - Cannot find [%lu] in party [%lu]", p->dwPID, p->dwLeaderPID); #endif } void CClientManager::QUERY_PARTY_STATE_CHANGE(CPeer* peer, TPacketPartyStateChange* p) { #ifdef BL_PARTY_UPDATE for (auto channels : channel_info) { TPartyMap & pm = m_map_pkChannelParty[channels]; itertype(pm) it = pm.find(p->dwLeaderPID); if (it == pm.end()) return; itertype(it->second) pit = it->second.find(p->dwPID); if (pit == it->second.end()) return; if (p->bFlag) pit->second.bRole = p->bRole; else pit->second.bRole = 0; ForwardPacket(HEADER_DG_PARTY_STATE_CHANGE, p, sizeof(TPacketPartyStateChange), channels, peer); } #else TPartyMap & pm = m_map_pkChannelParty[peer->GetChannel()]; itertype(pm) it = pm.find(p->dwLeaderPID); if (it == pm.end()) { sys_err("PARTY StateChange - Non exists [%lu] cannot state change [%lu]",p->dwLeaderPID, p->dwPID); return; } itertype(it->second) pit = it->second.find(p->dwPID); if (pit == it->second.end()) { sys_err("PARTY StateChange - Cannot find [%lu] in party [%lu]", p->dwPID, p->dwLeaderPID); return; } if (p->bFlag) pit->second.bRole = p->bRole; else pit->second.bRole = 0; ForwardPacket(HEADER_DG_PARTY_STATE_CHANGE, p, sizeof(TPacketPartyStateChange), peer->GetChannel(), peer); #endif sys_log(0, "PARTY StateChange [%lu] at [%lu] from %d %d",p->dwPID, p->dwLeaderPID, p->bRole, p->bFlag); } void CClientManager::QUERY_PARTY_SET_MEMBER_LEVEL(CPeer* peer, TPacketPartySetMemberLevel* p) { #ifdef BL_PARTY_UPDATE for (auto channels : channel_info) { TPartyMap & pm = m_map_pkChannelParty[channels]; itertype(pm) it = pm.find(p->dwLeaderPID); if (it == pm.end()) return; itertype(it->second) pit = it->second.find(p->dwPID); if (pit == it->second.end()) return; pit->second.bLevel = p->bLevel; ForwardPacket(HEADER_DG_PARTY_SET_MEMBER_LEVEL, p, sizeof(TPacketPartySetMemberLevel), channels); } #else TPartyMap & pm = m_map_pkChannelParty[peer->GetChannel()]; itertype(pm) it = pm.find(p->dwLeaderPID); if (it == pm.end()) { sys_err("PARTY SetMemberLevel - Non exists [%lu] cannot level change [%lu]",p->dwLeaderPID, p->dwPID); return; } itertype(it->second) pit = it->second.find(p->dwPID); if (pit == it->second.end()) { sys_err("PARTY SetMemberLevel - Cannot find [%lu] in party [%lu]", p->dwPID, p->dwLeaderPID); return; } pit->second.bLevel = p->bLevel; ForwardPacket(HEADER_DG_PARTY_SET_MEMBER_LEVEL, p, sizeof(TPacketPartySetMemberLevel), peer->GetChannel()); #endif sys_log(0, "PARTY SetMemberLevel pid [%lu] level %d",p->dwPID, p->bLevel); } Edited August 25, 2022 by Metin2 Dev Core X - External 2 Internal 3 1 Link to comment Share on other sites More sharing options...
Bot Metin2 Dev 4873 Posted May 30, 2018 Bot Share Posted May 30, 2018 On 5/20/2018 at 10:22 PM, Mali61 said: Yeah now party will create in all channels but still has some problem with online/offline problem.I don't have enough time but don't worry I will fix it. Link to comment Share on other sites More sharing options...
Hysteria 8 Posted August 11, 2021 Share Posted August 11, 2021 fix online/offline problem fix in " void CParty::SendPartyJoinAllToOne " and " void CParty::SendPartyUnlinkOneToAll " and " void CParty::SendPartyLinkOneToAll " and " void CParty::UpdateOnlineState " and " void CParty::UpdateOfflineState " function compare the file between yours and good luck party.cpp Spoiler #include "stdafx.h" #include "utils.h" #include "char.h" #include "party.h" #include "char_manager.h" #include "config.h" #include "p2p.h" #include "desc_client.h" #include "dungeon.h" #include "unique_item.h" #ifdef ENABLE_12ZI #include "zodiac_temple.h" #endif CPartyManager::CPartyManager() { Initialize(); } CPartyManager::~CPartyManager() { } void CPartyManager::Initialize() { m_bEnablePCParty = false; } void CPartyManager::DeleteAllParty() { TPCPartySet::iterator it = m_set_pkPCParty.begin(); while (it != m_set_pkPCParty.end()) { DeleteParty(*it); it = m_set_pkPCParty.begin(); } } bool CPartyManager::SetParty(LPCHARACTER ch) // PC¸¸ »ç؟ëاط¾ك ار´ظ!! { TPartyMap::iterator it = m_map_pkParty.find(ch->GetPlayerID()); if (it == m_map_pkParty.end()) return false; LPPARTY pParty = it->second; pParty->Link(ch); return true; } #ifdef ENABLE_PARTY_UPDATE void CPartyManager::P2PLogin(DWORD pid, const char* name, long mapIdx, long channel) #else void CPartyManager::P2PLogin(DWORD pid, const char* name) #endif { TPartyMap::iterator it = m_map_pkParty.find(pid); if (it == m_map_pkParty.end()) return; #ifdef ENABLE_PARTY_UPDATE it->second->UpdateOnlineState(pid, name, mapIdx, channel); #else it->second->UpdateOnlineState(pid, name); #endif } void CPartyManager::P2PLogout(DWORD pid) { TPartyMap::iterator it = m_map_pkParty.find(pid); if (it == m_map_pkParty.end()) return; it->second->UpdateOfflineState(pid); } void CPartyManager::P2PJoinParty(DWORD leader, DWORD pid, BYTE role) { TPartyMap::iterator it = m_map_pkParty.find(leader); if (it != m_map_pkParty.end()) { it->second->P2PJoin(pid); if (role >= PARTY_ROLE_MAX_NUM) role = PARTY_ROLE_NORMAL; it->second->SetRole(pid, role, true); } else { sys_err("No such party with leader [%d]", leader); } } void CPartyManager::P2PQuitParty(DWORD pid) { TPartyMap::iterator it = m_map_pkParty.find(pid); if (it != m_map_pkParty.end()) { it->second->P2PQuit(pid); } else { sys_err("No such party with member [%d]", pid); } } LPPARTY CPartyManager::P2PCreateParty(DWORD pid) { TPartyMap::iterator it = m_map_pkParty.find(pid); if (it != m_map_pkParty.end()) return it->second; LPPARTY pParty = M2_NEW CParty; m_set_pkPCParty.insert(pParty); SetPartyMember(pid, pParty); pParty->SetPCParty(true); pParty->P2PJoin(pid); return pParty; } void CPartyManager::P2PDeleteParty(DWORD pid) { TPartyMap::iterator it = m_map_pkParty.find(pid); if (it != m_map_pkParty.end()) { m_set_pkPCParty.erase(it->second); M2_DELETE(it->second); } else sys_err("PARTY P2PDeleteParty Cannot find party [%u]", pid); } LPPARTY CPartyManager::CreateParty(LPCHARACTER pLeader) { if (pLeader->GetParty()) return pLeader->GetParty(); LPPARTY pParty = M2_NEW CParty; if (pLeader->IsPC()) { //TPacketGGParty p; //p.header = HEADER_GG_PARTY; //p.subheader = PARTY_SUBHEADER_GG_CREATE; //p.pid = pLeader->GetPlayerID(); //P2P_MANAGER::instance().Send(&p, sizeof(p)); TPacketPartyCreate p; p.dwLeaderPID = pLeader->GetPlayerID(); db_clientdesc->DBPacket(HEADER_GD_PARTY_CREATE, 0, &p, sizeof(TPacketPartyCreate)); sys_log(0, "PARTY: Create %s pid %u", pLeader->GetName(), pLeader->GetPlayerID()); pParty->SetPCParty(true); pParty->Join(pLeader->GetPlayerID()); m_set_pkPCParty.insert(pParty); } else { pParty->SetPCParty(false); pParty->Join(pLeader->GetVID()); } pParty->Link(pLeader); return (pParty); } void CPartyManager::DeleteParty(LPPARTY pParty) { //TPacketGGParty p; //p.header = HEADER_GG_PARTY; //p.subheader = PARTY_SUBHEADER_GG_DESTROY; //p.pid = pParty->GetLeaderPID(); //P2P_MANAGER::instance().Send(&p, sizeof(p)); TPacketPartyDelete p; p.dwLeaderPID = pParty->GetLeaderPID(); db_clientdesc->DBPacket(HEADER_GD_PARTY_DELETE, 0, &p, sizeof(TPacketPartyDelete)); m_set_pkPCParty.erase(pParty); M2_DELETE(pParty); } void CPartyManager::SetPartyMember(DWORD dwPID, LPPARTY pParty) { TPartyMap::iterator it = m_map_pkParty.find(dwPID); if (pParty == NULL) { if (it != m_map_pkParty.end()) m_map_pkParty.erase(it); } else { if (it != m_map_pkParty.end()) { if (it->second != pParty) { it->second->Quit(dwPID); it->second = pParty; } } else m_map_pkParty.insert(TPartyMap::value_type(dwPID, pParty)); } } EVENTINFO(party_update_event_info) { DWORD pid; party_update_event_info() : pid( 0 ) { } }; ///////////////////////////////////////////////////////////////////////////// // // CParty begin! // ///////////////////////////////////////////////////////////////////////////// EVENTFUNC(party_update_event) { party_update_event_info* info = dynamic_cast<party_update_event_info*>( event->info ); if ( info == NULL ) { sys_err( "party_update_event> <Factor> Null pointer" ); return 0; } DWORD pid = info->pid; LPCHARACTER leader = CHARACTER_MANAGER::instance().FindByPID(pid); if (leader && leader->GetDesc()) { LPPARTY pParty = leader->GetParty(); if (pParty) pParty->Update(); } return PASSES_PER_SEC(3); } CParty::CParty() { Initialize(); } CParty::~CParty() { Destroy(); } void CParty::Initialize() { sys_log(2, "Party::Initialize"); m_iExpDistributionMode = PARTY_EXP_DISTRIBUTION_NON_PARITY; m_pkChrExpCentralize = NULL; m_dwLeaderPID = 0; m_eventUpdate = NULL; memset(&m_anRoleCount, 0, sizeof(m_anRoleCount)); memset(&m_anMaxRole, 0, sizeof(m_anMaxRole)); m_anMaxRole[PARTY_ROLE_LEADER] = 1; m_anMaxRole[PARTY_ROLE_NORMAL] = 32; m_dwPartyStartTime = get_dword_time(); m_iLongTimeExpBonus = 0; m_dwPartyHealTime = get_dword_time(); m_bPartyHealReady = false; m_bCanUsePartyHeal = false; m_iLeadership = 0; m_iExpBonus = 0; m_iAttBonus = 0; m_iDefBonus = 0; m_itNextOwner = m_memberMap.begin(); m_iCountNearPartyMember = 0; m_pkChrLeader = NULL; m_bPCParty = false; m_pkDungeon = NULL; m_pkDungeon_for_Only_party = NULL; #ifdef ENABLE_12ZI m_pkZodiac = NULL; m_pkZodiac_for_Only_party = NULL; #endif } void CParty::Destroy() { sys_log(2, "Party::Destroy"); // PC°، ¸¸µç ئؤئ¼¸é ئؤئ¼¸إ´دہْ؟، ¸ت؟،¼ PID¸¦ »èء¦اط¾ك ار´ظ. if (m_bPCParty) { for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it) CPartyManager::instance().SetPartyMember(it->first, NULL); } event_cancel(&m_eventUpdate); RemoveBonus(); TMemberMap::iterator it = m_memberMap.begin(); DWORD dwTime = get_dword_time(); while (it != m_memberMap.end()) { TMember & rMember = it->second; ++it; if (rMember.pCharacter) { if (rMember.pCharacter->GetDesc()) { TPacketGCPartyRemove p; p.header = HEADER_GC_PARTY_REMOVE; p.pid = rMember.pCharacter->GetPlayerID(); rMember.pCharacter->GetDesc()->Packet(&p, sizeof(p)); rMember.pCharacter->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ئؤئ¼> ئؤئ¼°، اط»ê µا¾ْ½ہ´د´ظ.")); } else { // NPCہد °و؟ى ہدء¤ ½أ°£ بؤ ہüإُ ءكہج ¾ئ´ز ¶§ »ç¶َءِ°ش اد´آ ہج؛¥ئ®¸¦ ½أہغ½أإ²´ظ. rMember.pCharacter->SetLastAttacked(dwTime); rMember.pCharacter->StartDestroyWhenIdleEvent(); } rMember.pCharacter->SetParty(NULL); } } m_memberMap.clear(); m_itNextOwner = m_memberMap.begin(); if (m_pkDungeon_for_Only_party != NULL) { m_pkDungeon_for_Only_party->SetPartyNull(); m_pkDungeon_for_Only_party = NULL; } #ifdef ENABLE_12ZI if (m_pkZodiac_for_Only_party != NULL) { m_pkZodiac_for_Only_party->SetPartyNull(); m_pkZodiac_for_Only_party = NULL; } #endif } void CParty::ChatPacketToAllMember(BYTE type, const char* format, ...) { char chatbuf[CHAT_MAX_LEN + 1]; va_list args; va_start(args, format); vsnprintf(chatbuf, sizeof(chatbuf), format, args); va_end(args); TMemberMap::iterator it; for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { TMember & rMember = it->second; if (rMember.pCharacter) { if (rMember.pCharacter->GetDesc()) { rMember.pCharacter->ChatPacket(type, "%s", chatbuf); } } } } DWORD CParty::GetLeaderPID() { return m_dwLeaderPID; } DWORD CParty::GetMemberCount() { return m_memberMap.size(); } void CParty::P2PJoin(DWORD dwPID) { TMemberMap::iterator it = m_memberMap.find(dwPID); if (it == m_memberMap.end()) { TMember Member; Member.pCharacter = NULL; Member.bNear = false; if (m_memberMap.empty()) { Member.bRole = PARTY_ROLE_LEADER; m_dwLeaderPID = dwPID; } else Member.bRole = PARTY_ROLE_NORMAL; if (m_bPCParty) { LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(dwPID); if (ch) { sys_log(0, "PARTY: Join %s pid %u leader %u", ch->GetName(), dwPID, m_dwLeaderPID); Member.strName = ch->GetName(); if (Member.bRole == PARTY_ROLE_LEADER) m_iLeadership = ch->GetLeadershipSkillLevel(); #ifdef ENABLE_PARTY_UPDATE Member.mapIdx = ch->GetMapIndex(); Member.channel = g_bChannel; #endif } else { CCI * pcci = P2P_MANAGER::instance().FindByPID(dwPID); if (!pcci); else if (pcci->bChannel == g_bChannel) { Member.strName = pcci->szName; #ifdef ENABLE_PARTY_UPDATE Member.mapIdx = pcci->lMapIndex; Member.channel = pcci->bChannel; #endif } else sys_err("member is not in same channel PID: %u channel %d, this channel %d", dwPID, pcci->bChannel, g_bChannel); } } sys_log(2, "PARTY[%d] MemberCountChange %d -> %d", GetLeaderPID(), GetMemberCount(), GetMemberCount()+1); m_memberMap.insert(TMemberMap::value_type(dwPID, Member)); if (m_memberMap.size() == 1) m_itNextOwner = m_memberMap.begin(); if (m_bPCParty) { CPartyManager::instance().SetPartyMember(dwPID, this); SendPartyJoinOneToAll(dwPID); LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(dwPID); if (ch) SendParameter(ch); } } if (m_pkDungeon) { m_pkDungeon->QuitParty(this); } #ifdef ENABLE_12ZI if (m_pkZodiac) { m_pkZodiac->QuitParty(this); } #endif } void CParty::Join(DWORD dwPID) { P2PJoin(dwPID); if (m_bPCParty) { TPacketPartyAdd p; p.dwLeaderPID = GetLeaderPID(); p.dwPID = dwPID; p.bState = PARTY_ROLE_NORMAL; // #0000790: [M2EU] CZ إ©·،½¬ ءُ°،: أت±âب ءك؟ن! db_clientdesc->DBPacket(HEADER_GD_PARTY_ADD, 0, &p, sizeof(p)); } } void CParty::P2PQuit(DWORD dwPID) { TMemberMap::iterator it = m_memberMap.find(dwPID); if (it == m_memberMap.end()) return; if (m_bPCParty) SendPartyRemoveOneToAll(dwPID); if (it == m_itNextOwner) IncreaseOwnership(); if (m_bPCParty) RemoveBonusForOne(dwPID); LPCHARACTER ch = it->second.pCharacter; BYTE bRole = it->second.bRole; m_memberMap.erase(it); sys_log(2, "PARTY[%d] MemberCountChange %d -> %d", GetLeaderPID(), GetMemberCount(), GetMemberCount() - 1); if (bRole < PARTY_ROLE_MAX_NUM) { --m_anRoleCount[bRole]; } else { sys_err("ROLE_COUNT_QUIT_ERROR: INDEX(%d) > MAX(%d)", bRole, PARTY_ROLE_MAX_NUM); } if (ch) { ch->SetParty(NULL); ComputeRolePoint(ch, bRole, false); } if (m_bPCParty) CPartyManager::instance().SetPartyMember(dwPID, NULL); // ¸®´ُ°، ³ھ°،¸é ئؤئ¼´آ اط»êµا¾î¾ك ار´ظ. if (bRole == PARTY_ROLE_LEADER) CPartyManager::instance().DeleteParty(this); // ہج ¾ئ·،´آ ؤعµه¸¦ أك°،ادءِ ¸» °ح!!! ہ§ DeleteParty اد¸é this´آ ¾ّ´ظ. } void CParty::Quit(DWORD dwPID) { // Always PC P2PQuit(dwPID); if (m_bPCParty && dwPID != GetLeaderPID()) { //TPacketGGParty p; //p.header = HEADER_GG_PARTY; //p.subheader = PARTY_SUBHEADER_GG_QUIT; //p.pid = dwPID; //p.leaderpid = GetLeaderPID(); //P2P_MANAGER::instance().Send(&p, sizeof(p)); TPacketPartyRemove p; p.dwPID = dwPID; p.dwLeaderPID = GetLeaderPID(); db_clientdesc->DBPacket(HEADER_GD_PARTY_REMOVE, 0, &p, sizeof(p)); } } void CParty::Link(LPCHARACTER pkChr) { TMemberMap::iterator it; if (pkChr->IsPC()) it = m_memberMap.find(pkChr->GetPlayerID()); else it = m_memberMap.find(pkChr->GetVID()); if (it == m_memberMap.end()) { sys_err("%s is not member of this party", pkChr->GetName()); return; } // اأ·¹ہج¾î ئؤئ¼ہد °و؟ى ¾÷µ¥ہجئ® ہج؛¥ئ® »¼؛ if (m_bPCParty && !m_eventUpdate) { party_update_event_info* info = AllocEventInfo<party_update_event_info>(); info->pid = m_dwLeaderPID; m_eventUpdate = event_create(party_update_event, info, PASSES_PER_SEC(3)); } if (it->second.bRole == PARTY_ROLE_LEADER) m_pkChrLeader = pkChr; sys_log(2, "PARTY[%d] %s linked to party", GetLeaderPID(), pkChr->GetName()); it->second.pCharacter = pkChr; pkChr->SetParty(this); if (pkChr->IsPC()) { if (it->second.strName.empty()) { it->second.strName = pkChr->GetName(); } SendPartyJoinOneToAll(pkChr->GetPlayerID()); SendPartyJoinAllToOne(pkChr); SendPartyLinkOneToAll(pkChr); SendPartyLinkAllToOne(pkChr); SendPartyInfoAllToOne(pkChr); SendPartyInfoOneToAll(pkChr); SendParameter(pkChr); if (GetDungeon() && GetDungeon()->GetMapIndex() == pkChr->GetMapIndex()) { pkChr->SetDungeon(GetDungeon()); } #ifdef ENABLE_12ZI if (GetZodiac() && GetZodiac()->GetMapIndex() == pkChr->GetMapIndex()) { pkChr->SetZodiac(GetZodiac()); } #endif RequestSetMemberLevel(pkChr->GetPlayerID(), pkChr->GetLevel()); #ifdef ENABLE_PARTY_UPDATE RequestSetMemberMapIndex(pkChr->GetPlayerID(), pkChr->GetMapIndex()); RequestSetMemberChannel(pkChr->GetPlayerID(), g_bChannel); #endif } } void CParty::RequestSetMemberLevel(DWORD pid, BYTE level) { TPacketPartySetMemberLevel p; p.dwLeaderPID = GetLeaderPID(); p.dwPID = pid; p.bLevel = level; db_clientdesc->DBPacket(HEADER_GD_PARTY_SET_MEMBER_LEVEL, 0, &p, sizeof(TPacketPartySetMemberLevel)); } void CParty::P2PSetMemberLevel(DWORD pid, BYTE level) { if (!m_bPCParty) return; TMemberMap::iterator it; sys_log(0, "PARTY P2PSetMemberLevel leader %d pid %d level %d", GetLeaderPID(), pid, level); it = m_memberMap.find(pid); if (it != m_memberMap.end()) { it->second.bLevel = level; } } #ifdef ENABLE_PARTY_UPDATE void CParty::RequestSetMemberMapIndex(DWORD pid, long mapIdx) { TPacketPartySetMemberMapIndex p; p.dwLeaderPID = GetLeaderPID(); p.dwPID = pid; p.mapIdx = mapIdx; db_clientdesc->DBPacket(HEADER_GD_PARTY_SET_MEMBER_MAP_INDEX, 0, &p, sizeof(TPacketPartySetMemberMapIndex)); } void CParty::P2PSetMemberMapIndex(DWORD pid, long mapIdx) { if (!m_bPCParty) return; TMemberMap::iterator it; sys_log(0, "PARTY P2PSetMemberMapIndex leader %d pid %d mapIdx %d", GetLeaderPID(), pid, mapIdx); it = m_memberMap.find(pid); if (it != m_memberMap.end()) { it->second.mapIdx = mapIdx; } } void CParty::RequestSetMemberChannel(DWORD pid, long channel) { TPacketPartySetMemberChannel p; p.dwLeaderPID = GetLeaderPID(); p.dwPID = pid; p.channel = channel; db_clientdesc->DBPacket(HEADER_GD_PARTY_SET_MEMBER_CHANNEL, 0, &p, sizeof(TPacketPartySetMemberChannel)); } void CParty::P2PSetMemberChannel(DWORD pid, long channel) { if (!m_bPCParty) return; TMemberMap::iterator it; sys_log(0, "PARTY P2PSetMemberChannel leader %d pid %d ch %d", GetLeaderPID(), pid, channel); it = m_memberMap.find(pid); if (it != m_memberMap.end()) { it->second.channel = channel; } } #endif namespace { struct FExitDungeon { void operator()(LPCHARACTER ch) { ch->ExitToSavedLocation(); } }; } void CParty::Unlink(LPCHARACTER pkChr) { TMemberMap::iterator it; if (pkChr->IsPC()) it = m_memberMap.find(pkChr->GetPlayerID()); else it = m_memberMap.find(pkChr->GetVID()); if (it == m_memberMap.end()) { sys_err("%s is not member of this party", pkChr->GetName()); return; } if (pkChr->IsPC()) { SendPartyUnlinkOneToAll(pkChr); if (it->second.bRole == PARTY_ROLE_LEADER) { RemoveBonus(); #ifdef ENABLE_12ZI if (it->second.pCharacter->GetDungeon() || it->second.pCharacter->GetZodiac()) #else if (it->second.pCharacter->GetDungeon()) #endif { FExitDungeon f; ForEachNearMember(f); } } } if (it->second.bRole == PARTY_ROLE_LEADER) m_pkChrLeader = NULL; it->second.pCharacter = NULL; pkChr->SetParty(NULL); } void CParty::SendPartyRemoveOneToAll(DWORD pid) { TMemberMap::iterator it; TPacketGCPartyRemove p; p.header = HEADER_GC_PARTY_REMOVE; p.pid = pid; for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { if (it->second.pCharacter && it->second.pCharacter->GetDesc()) it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p)); } } void CParty::SendPartyJoinOneToAll(DWORD pid) { const TMember& r = m_memberMap[pid]; TPacketGCPartyAdd p; p.header = HEADER_GC_PARTY_ADD; p.pid = pid; strlcpy(p.name, r.strName.c_str(), sizeof(p.name)); #ifdef ENABLE_PARTY_UPDATE p.mapIdx = r.mapIdx; p.channel = r.channel; #endif for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { if (it->second.pCharacter && it->second.pCharacter->GetDesc()) it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p)); } } void CParty::SendPartyJoinAllToOne(LPCHARACTER ch) { if (!ch->GetDesc()) return; for (TMemberMap::iterator it = m_memberMap.begin();it!= m_memberMap.end(); ++it) { CCI *pCCI = P2P_MANAGER::instance().Find(it->second.strName.c_str()); if (it->second.pCharacter || pCCI) UpdateOnlineState(it->first, it->second.strName.c_str(), it->second.channel, it->second.mapIdx); else UpdateOfflineState(it->first); } } void CParty::SendPartyUnlinkOneToAll(LPCHARACTER ch) { if (!ch->GetDesc()) return; TMemberMap::iterator it; TPacketGCPartyLink p; p.header = HEADER_GC_PARTY_UNLINK; p.pid = ch->GetPlayerID(); p.vid = (DWORD)ch->GetVID(); for (it = m_memberMap.begin();it!= m_memberMap.end(); ++it) { #ifdef ENABLE_PARTY_UPDATE CCI *pCCI = P2P_MANAGER::instance().Find(it->second.strName.c_str()); if (it->second.pCharacter && it->second.pCharacter->GetDesc()) it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p)); else if (pCCI) pCCI->pkDesc->Packet(&p, sizeof(p)); #else if (it->second.pCharacter && it->second.pCharacter->GetDesc()) it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p)); #endif } } void CParty::SendPartyLinkOneToAll(LPCHARACTER ch) { if (!ch->GetDesc()) return; TMemberMap::iterator it; TPacketGCPartyLink p; p.header = HEADER_GC_PARTY_LINK; p.vid = ch->GetVID(); p.pid = ch->GetPlayerID(); #ifdef ENABLE_PARTY_UPDATE p.mapIdx = ch->GetMapIndex(); p.channel = g_bChannel; #endif for (it = m_memberMap.begin();it!= m_memberMap.end(); ++it) { #ifdef ENABLE_PARTY_UPDATE CCI *pCCI = P2P_MANAGER::instance().Find(it->second.strName.c_str()); if (it->second.pCharacter && it->second.pCharacter->GetDesc()) it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p)); else if (pCCI) pCCI->pkDesc->Packet(&p, sizeof(p)); #else if (it->second.pCharacter && it->second.pCharacter->GetDesc()) it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p)); #endif } } void CParty::SendPartyLinkAllToOne(LPCHARACTER ch) { if (!ch->GetDesc()) return; TMemberMap::iterator it; TPacketGCPartyLink p; p.header = HEADER_GC_PARTY_LINK; for (it = m_memberMap.begin();it!= m_memberMap.end(); ++it) { if (it->second.pCharacter) { p.vid = it->second.pCharacter->GetVID(); p.pid = it->second.pCharacter->GetPlayerID(); #ifdef ENABLE_PARTY_UPDATE p.mapIdx = it->second.pCharacter->GetMapIndex(); p.channel = g_bChannel; #endif ch->GetDesc()->Packet(&p, sizeof(p)); } } } void CParty::SendPartyInfoOneToAll(DWORD pid) { TMemberMap::iterator it = m_memberMap.find(pid); if (it == m_memberMap.end()) return; if (it->second.pCharacter) { SendPartyInfoOneToAll(it->second.pCharacter); return; } // Data Building TPacketGCPartyUpdate p; memset(&p, 0, sizeof(p)); p.header = HEADER_GC_PARTY_UPDATE; p.pid = pid; p.percent_hp = 255; p.role = it->second.bRole; for (it = m_memberMap.begin();it!= m_memberMap.end(); ++it) { if ((it->second.pCharacter) && (it->second.pCharacter->GetDesc())) { //sys_log(2, "PARTY send info %s[%d] to %s[%d]", ch->GetName(), (DWORD)ch->GetVID(), it->second.pCharacter->GetName(), (DWORD)it->second.pCharacter->GetVID()); it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p)); } } } void CParty::SendPartyInfoOneToAll(LPCHARACTER ch) { if (!ch->GetDesc()) return; TMemberMap::iterator it; // Data Building TPacketGCPartyUpdate p; ch->BuildUpdatePartyPacket(p); for (it = m_memberMap.begin();it!= m_memberMap.end(); ++it) { if ((it->second.pCharacter) && (it->second.pCharacter->GetDesc())) { sys_log(2, "PARTY send info %s[%d] to %s[%d]", ch->GetName(), (DWORD)ch->GetVID(), it->second.pCharacter->GetName(), (DWORD)it->second.pCharacter->GetVID()); it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p)); } } } void CParty::SendPartyInfoAllToOne(LPCHARACTER ch) { TMemberMap::iterator it; TPacketGCPartyUpdate p; for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { if (!it->second.pCharacter) { DWORD pid = it->first; memset(&p, 0, sizeof(p)); p.header = HEADER_GC_PARTY_UPDATE; p.pid = pid; p.percent_hp = 255; p.role = it->second.bRole; ch->GetDesc()->Packet(&p, sizeof(p)); continue; } it->second.pCharacter->BuildUpdatePartyPacket(p); sys_log(2, "PARTY send info %s[%d] to %s[%d]", it->second.pCharacter->GetName(), (DWORD)it->second.pCharacter->GetVID(), ch->GetName(), (DWORD)ch->GetVID()); ch->GetDesc()->Packet(&p, sizeof(p)); } } void CParty::SendMessage(LPCHARACTER ch, BYTE bMsg, DWORD dwArg1, DWORD dwArg2) { if (ch->GetParty() != this) { sys_err("%s is not member of this party %p", ch->GetName(), this); return; } switch (bMsg) { case PM_ATTACK: break; case PM_RETURN: { TMemberMap::iterator it = m_memberMap.begin(); while (it != m_memberMap.end()) { TMember & rMember = it->second; ++it; LPCHARACTER pkChr; if ((pkChr = rMember.pCharacter) && ch != pkChr) { DWORD x = dwArg1 + number(-500, 500); DWORD y = dwArg2 + number(-500, 500); pkChr->SetVictim(NULL); pkChr->SetRotationToXY(x, y); if (pkChr->Goto(x, y)) { LPCHARACTER victim = pkChr->GetVictim(); sys_log(0, "%s %p RETURN victim %p", pkChr->GetName(), get_pointer(pkChr), get_pointer(victim)); pkChr->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0); } } } } break; case PM_ATTACKED_BY: // °ّ°ف ¹ق¾زہ½, ¸®´ُ؟،°ش µµ؟ٍہ» ؟نأ» { // ¸®´ُ°، ¾ّہ» ¶§ LPCHARACTER pkChrVictim = ch->GetVictim(); if (!pkChrVictim) return; TMemberMap::iterator it = m_memberMap.begin(); while (it != m_memberMap.end()) { TMember & rMember = it->second; ++it; LPCHARACTER pkChr; if ((pkChr = rMember.pCharacter) && ch != pkChr) { if (pkChr->CanBeginFight()) pkChr->BeginFight(pkChrVictim); } } } break; case PM_AGGRO_INCREASE: { LPCHARACTER victim = CHARACTER_MANAGER::instance().Find(dwArg2); if (!victim) return; TMemberMap::iterator it = m_memberMap.begin(); while (it != m_memberMap.end()) { TMember & rMember = it->second; ++it; LPCHARACTER pkChr; if ((pkChr = rMember.pCharacter) && ch != pkChr) { pkChr->UpdateAggrPoint(victim, DAMAGE_TYPE_SPECIAL, dwArg1); } } } break; } } LPCHARACTER CParty::GetLeaderCharacter() { return m_memberMap[GetLeaderPID()].pCharacter; } bool CParty::SetRole(DWORD dwPID, BYTE bRole, bool bSet) { TMemberMap::iterator it = m_memberMap.find(dwPID); if (it == m_memberMap.end()) { return false; } LPCHARACTER ch = it->second.pCharacter; if (bSet) { if (m_anRoleCount[bRole] >= m_anMaxRole[bRole]) return false; if (it->second.bRole != PARTY_ROLE_NORMAL) return false; it->second.bRole = bRole; if (ch && GetLeader()) ComputeRolePoint(ch, bRole, true); if (bRole < PARTY_ROLE_MAX_NUM) { ++m_anRoleCount[bRole]; } else { sys_err("ROLE_COUNT_INC_ERROR: INDEX(%d) > MAX(%d)", bRole, PARTY_ROLE_MAX_NUM); } } else { if (it->second.bRole == PARTY_ROLE_LEADER) return false; if (it->second.bRole == PARTY_ROLE_NORMAL) return false; it->second.bRole = PARTY_ROLE_NORMAL; if (ch && GetLeader()) ComputeRolePoint(ch, PARTY_ROLE_NORMAL, false); if (bRole < PARTY_ROLE_MAX_NUM) { --m_anRoleCount[bRole]; } else { sys_err("ROLE_COUNT_DEC_ERROR: INDEX(%d) > MAX(%d)", bRole, PARTY_ROLE_MAX_NUM); } } SendPartyInfoOneToAll(dwPID); return true; } BYTE CParty::GetRole(DWORD pid) { TMemberMap::iterator it = m_memberMap.find(pid); if (it == m_memberMap.end()) return PARTY_ROLE_NORMAL; else return it->second.bRole; } bool CParty::IsRole(DWORD pid, BYTE bRole) { TMemberMap::iterator it = m_memberMap.find(pid); if (it == m_memberMap.end()) return false; return it->second.bRole == bRole; } void CParty::RemoveBonus() { TMemberMap::iterator it; for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { LPCHARACTER ch; if ((ch = it->second.pCharacter)) { ComputeRolePoint(ch, it->second.bRole, false); } it->second.bNear = false; } } void CParty::RemoveBonusForOne(DWORD pid) { TMemberMap::iterator it = m_memberMap.find(pid); if (it == m_memberMap.end()) return; LPCHARACTER ch; if ((ch = it->second.pCharacter)) ComputeRolePoint(ch, it->second.bRole, false); } void CParty::HealParty() { // XXX DELETEME إ¬¶َہج¾ًئ® ؟د·لµة¶§±îءِ { return; } if (!m_bPartyHealReady) return; TMemberMap::iterator it; LPCHARACTER l = GetLeaderCharacter(); for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { if (!it->second.pCharacter) continue; LPCHARACTER ch = it->second.pCharacter; if (DISTANCE_APPROX(l->GetX()-ch->GetX(), l->GetY()-ch->GetY()) < PARTY_DEFAULT_RANGE) { ch->PointChange(POINT_HP, ch->GetMaxHP()-ch->GetHP()); ch->PointChange(POINT_SP, ch->GetMaxSP()-ch->GetSP()); } } m_bPartyHealReady = false; m_dwPartyHealTime = get_dword_time(); } void CParty::SummonToLeader(DWORD pid) { int xy[12][2] = { { 250, 0 }, { 216, 125 }, { 125, 216 }, { 0, 250 }, { -125, 216 }, { -216, 125 }, { -250, 0 }, { -216, -125 }, { -125, -216 }, { 0, -250 }, { 125, -216 }, { 216, -125 }, }; int n = 0; int x[12], y[12]; SECTREE_MANAGER & s = SECTREE_MANAGER::instance(); LPCHARACTER l = GetLeaderCharacter(); if (m_memberMap.find(pid) == m_memberMap.end()) { l->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ئؤئ¼> ¼زب¯اد·ء´آ ´ë»َہ» أ£ہ» ¼ِ ¾ّ½ہ´د´ظ.")); return; } LPCHARACTER ch = m_memberMap[pid].pCharacter; if (!ch) { l->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ئؤئ¼> ¼زب¯اد·ء´آ ´ë»َہ» أ£ہ» ¼ِ ¾ّ½ہ´د´ظ.")); return; } if (ch->IsDead()) { l->ChatPacket(CHAT_TYPE_INFO, " <مجموعة> لا تستطيع سحب شخص ميت "); return; } if (!ch->CanSummon(m_iLeadership)) { l->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ئؤئ¼> ´ë»َہ» ¼زب¯از ¼ِ ¾ّ½ہ´د´ظ.")); return; } for (int i = 0; i < 12; ++i) { PIXEL_POSITION p; if (s.GetMovablePosition(l->GetMapIndex(), l->GetX() + xy [i][0], l->GetY() + xy[i][1], p)) { x[n] = p.x; y[n] = p.y; n++; } } if (n == 0) l->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ئؤئ¼> ئؤئ¼؟ّہ» اِہç ہ§ؤ،·خ ¼زب¯از ¼ِ ¾ّ½ہ´د´ظ.")); else { int i = number(0, n - 1); ch->Show(l->GetMapIndex(), x[i], y[i]); ch->Stop(); } } void CParty::IncreaseOwnership() { if (m_memberMap.empty()) { m_itNextOwner = m_memberMap.begin(); return; } if (m_itNextOwner == m_memberMap.end()) m_itNextOwner = m_memberMap.begin(); else { m_itNextOwner++; if (m_itNextOwner == m_memberMap.end()) m_itNextOwner = m_memberMap.begin(); } } LPCHARACTER CParty::GetNextOwnership(LPCHARACTER ch, long x, long y) { if (m_itNextOwner == m_memberMap.end()) return ch; int size = m_memberMap.size(); while (size-- > 0) { LPCHARACTER pkMember = m_itNextOwner->second.pCharacter; if (pkMember && DISTANCE_APPROX(pkMember->GetX() - x, pkMember->GetY() - y) < 3000) { IncreaseOwnership(); return pkMember; } IncreaseOwnership(); } return ch; } void CParty::ComputeRolePoint(LPCHARACTER ch, BYTE bRole, bool bAdd) { if (!bAdd) { bool state = false; const DWORD Bonuslar[] = { POINT_PARTY_ATTACKER_BONUS, POINT_PARTY_TANKER_BONUS, POINT_PARTY_BUFFER_BONUS, POINT_PARTY_SKILL_MASTER_BONUS, POINT_PARTY_DEFENDER_BONUS, POINT_PARTY_HASTE_BONUS }; for (size_t i = 0; i < sizeof(Bonuslar) / sizeof(DWORD); ++i) { if (ch->GetPoint(Bonuslar[i])) { ch->PointChange(Bonuslar[i], -ch->GetPoint(Bonuslar[i])); state = true; } } if (state) { ch->ComputeBattlePoints(); ch->ComputePoints(); } return; } float k = (float) ch->GetSkillPowerByLevel( MIN(SKILL_MAX_LEVEL, m_iLeadership ) )/ 100.0f; switch (bRole) { case PARTY_ROLE_ATTACKER: { int iBonus = (int) (10 + 60 * k); if (ch->GetPoint(POINT_PARTY_ATTACKER_BONUS) != iBonus) { ch->PointChange(POINT_PARTY_ATTACKER_BONUS, iBonus - ch->GetPoint(POINT_PARTY_ATTACKER_BONUS)); ch->ComputePoints(); } } break; case PARTY_ROLE_TANKER: { int iBonus = (int) (50 + 1450 * k); if (ch->GetPoint(POINT_PARTY_TANKER_BONUS) != iBonus) { ch->PointChange(POINT_PARTY_TANKER_BONUS, iBonus - ch->GetPoint(POINT_PARTY_TANKER_BONUS)); ch->ComputePoints(); } } break; case PARTY_ROLE_BUFFER: { int iBonus = (int) (5 + 45 * k); if (ch->GetPoint(POINT_PARTY_BUFFER_BONUS) != iBonus) { ch->PointChange(POINT_PARTY_BUFFER_BONUS, iBonus - ch->GetPoint(POINT_PARTY_BUFFER_BONUS)); } } break; case PARTY_ROLE_SKILL_MASTER: { int iBonus = (int) (25 + 600 * k); if (ch->GetPoint(POINT_PARTY_SKILL_MASTER_BONUS) != iBonus) { ch->PointChange(POINT_PARTY_SKILL_MASTER_BONUS, iBonus - ch->GetPoint(POINT_PARTY_SKILL_MASTER_BONUS)); ch->ComputePoints(); } } break; case PARTY_ROLE_HASTE: { int iBonus = (int) (1+5*k); if (ch->GetPoint(POINT_PARTY_HASTE_BONUS) != iBonus) { ch->PointChange(POINT_PARTY_HASTE_BONUS, iBonus - ch->GetPoint(POINT_PARTY_HASTE_BONUS)); ch->ComputePoints(); } } break; case PARTY_ROLE_DEFENDER: { int iBonus = (int) (5+30*k); if (ch->GetPoint(POINT_PARTY_DEFENDER_BONUS) != iBonus) { ch->PointChange(POINT_PARTY_DEFENDER_BONUS, iBonus - ch->GetPoint(POINT_PARTY_DEFENDER_BONUS)); ch->ComputePoints(); } } break; } } void CParty::Update() { sys_log(1, "PARTY::Update"); LPCHARACTER l = GetLeaderCharacter(); if (!l) return; TMemberMap::iterator it; int iNearMember = 0; bool bResendAll = false; for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { LPCHARACTER ch = it->second.pCharacter; it->second.bNear = false; if (!ch) continue; if (l->GetDungeon()) it->second.bNear = l->GetDungeon() == ch->GetDungeon(); #ifdef ENABLE_12ZI else if (l->GetZodiac()) it->second.bNear = l->GetZodiac() == ch->GetZodiac(); #endif else it->second.bNear = (DISTANCE_APPROX(l->GetX()-ch->GetX(), l->GetY()-ch->GetY()) < PARTY_DEFAULT_RANGE); if (it->second.bNear) { ++iNearMember; } } if (iNearMember <= 1 && !l->GetDungeon()) { for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) it->second.bNear = false; iNearMember = 0; } #ifdef ENABLE_12ZI if (iNearMember <= 1 && !l->GetZodiac()) { for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) it->second.bNear = false; iNearMember = 0; } #endif if (iNearMember != m_iCountNearPartyMember) { m_iCountNearPartyMember = iNearMember; bResendAll = true; } m_iLeadership = l->GetLeadershipSkillLevel(); int iNewExpBonus = ComputePartyBonusExpPercent(); m_iAttBonus = ComputePartyBonusAttackGrade(); m_iDefBonus = ComputePartyBonusDefenseGrade(); if (m_iExpBonus != iNewExpBonus) { bResendAll = true; m_iExpBonus = iNewExpBonus; } bool bLongTimeExpBonusChanged = false; // ئؤئ¼ °ل¼؛ بؤ أو؛ذار ½أ°£ہج ءِ³ھ¸é °واèؤ، ؛¸³ت½؛¸¦ ¹ق´آ´ظ. if (!m_iLongTimeExpBonus && (get_dword_time() - m_dwPartyStartTime > PARTY_ENOUGH_MINUTE_FOR_EXP_BONUS * 60 * 1000 / (g_iUseLocale?1:2))) { bLongTimeExpBonusChanged = true; m_iLongTimeExpBonus = 5; bResendAll = true; } for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { LPCHARACTER ch = it->second.pCharacter; if (!ch) continue; if (bLongTimeExpBonusChanged && ch->GetDesc()) ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ئؤئ¼ہا اùµ؟·آہج ³ô¾ئء® ءِ±ف؛خإح أك°، °واèؤ، ؛¸³ت½؛¸¦ ¹ق½ہ´د´ظ.")); bool bNear = it->second.bNear; ComputeRolePoint(ch, it->second.bRole, bNear); if (bNear) { if (!bResendAll) SendPartyInfoOneToAll(ch); } } // PARTY_ROLE_LIMIT_LEVEL_BUG_FIX m_anMaxRole[PARTY_ROLE_ATTACKER] = m_iLeadership >= 10 ? 1 : 0; m_anMaxRole[PARTY_ROLE_HASTE] = m_iLeadership >= 20 ? 1 : 0; m_anMaxRole[PARTY_ROLE_TANKER] = m_iLeadership >= 20 ? 1 : 0; m_anMaxRole[PARTY_ROLE_BUFFER] = m_iLeadership >= 25 ? 1 : 0; m_anMaxRole[PARTY_ROLE_SKILL_MASTER] = m_iLeadership >= 35 ? 1 : 0; m_anMaxRole[PARTY_ROLE_DEFENDER] = m_iLeadership >= 40 ? 1 : 0; m_anMaxRole[PARTY_ROLE_ATTACKER] += m_iLeadership >= 40 ? 1 : 0; // END_OF_PARTY_ROLE_LIMIT_LEVEL_BUG_FIX // Party Heal Update if (!m_bPartyHealReady) { if (!m_bCanUsePartyHeal && m_iLeadership >= 18) m_dwPartyHealTime = get_dword_time(); m_bCanUsePartyHeal = m_iLeadership >= 18; // إë¼ض·آ 18 ہج»َہ؛ بْہ» »ç؟ëاز ¼ِ ہضہ½. // إë¼ض·آ 40ہج»َہ؛ ئؤئ¼ بْ ؤًإ¸ہسہج ہû´ظ. DWORD PartyHealCoolTime = (m_iLeadership >= 40) ? PARTY_HEAL_COOLTIME_SHORT * 60 * 1000 : PARTY_HEAL_COOLTIME_LONG * 60 * 1000; if (m_bCanUsePartyHeal) { if (get_dword_time() > m_dwPartyHealTime + PartyHealCoolTime) { m_bPartyHealReady = true; // send heal ready if (0) // XXX DELETEME إ¬¶َہج¾ًئ® ؟د·لµة¶§±îءِ if (GetLeaderCharacter()) GetLeaderCharacter()->ChatPacket(CHAT_TYPE_COMMAND, "PartyHealReady"); } } } if (bResendAll) { for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it) if (it->second.pCharacter) SendPartyInfoOneToAll(it->second.pCharacter); } } #ifdef ENABLE_PARTY_UPDATE void CParty::UpdateOnlineState(DWORD dwPID, const char* name, long mapIdx, long channel) #else void CParty::UpdateOnlineState(DWORD dwPID, const char* name) #endif { TMember& r = m_memberMap[dwPID]; TPacketGCPartyAdd p; p.header = HEADER_GC_PARTY_ADD; p.pid = dwPID; r.strName = name; strlcpy(p.name, name, sizeof(p.name)); #ifdef ENABLE_PARTY_UPDATE p.mapIdx = mapIdx; p.channel = channel; #endif for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { #ifdef ENABLE_PARTY_UPDATE CCI *pCCI = P2P_MANAGER::instance().Find(it->second.strName.c_str()); if (it->second.pCharacter && it->second.pCharacter->GetDesc()) it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p)); else if (pCCI) pCCI->pkDesc->Packet(&p, sizeof(p)); #else if (it->second.pCharacter && it->second.pCharacter->GetDesc()) it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p)); #endif } } void CParty::UpdateOfflineState(DWORD dwPID) { //const TMember& r = m_memberMap[dwPID]; TPacketGCPartyAdd p; p.header = HEADER_GC_PARTY_ADD; p.pid = dwPID; memset(p.name, 0, CHARACTER_NAME_MAX_LEN+1); #ifdef ENABLE_PARTY_UPDATE p.mapIdx = 0; p.channel = 0; #endif for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { #ifdef ENABLE_PARTY_UPDATE CCI *pCCI = P2P_MANAGER::instance().Find(it->second.strName.c_str()); if (it->second.pCharacter && it->second.pCharacter->GetDesc()) it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p)); else if (pCCI) pCCI->pkDesc->Packet(&p, sizeof(p)); #else if (it->second.pCharacter && it->second.pCharacter->GetDesc()) it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p)); #endif } } int CParty::GetFlag(const std::string& name) { TFlagMap::iterator it = m_map_iFlag.find(name); if (it != m_map_iFlag.end()) { //sys_log(0,"PARTY GetFlag %s %d", name.c_str(), it->second); return it->second; } //sys_log(0,"PARTY GetFlag %s 0", name.c_str()); return 0; } void CParty::SetFlag(const std::string& name, int value) { TFlagMap::iterator it = m_map_iFlag.find(name); //sys_log(0,"PARTY SetFlag %s %d", name.c_str(), value); if (it == m_map_iFlag.end()) { m_map_iFlag.insert(make_pair(name, value)); } else if (it->second != value) { it->second = value; } } void CParty::SetDungeon(LPDUNGEON pDungeon) { m_pkDungeon = pDungeon; m_map_iFlag.clear(); } LPDUNGEON CParty::GetDungeon() { return m_pkDungeon; } void CParty::SetDungeon_for_Only_party(LPDUNGEON pDungeon) { m_pkDungeon_for_Only_party = pDungeon; } LPDUNGEON CParty::GetDungeon_for_Only_party() { return m_pkDungeon_for_Only_party; } #ifdef ENABLE_12ZI void CParty::SetZodiac(LPZODIAC pZodiac) { m_pkZodiac = pZodiac; m_map_iFlag.clear(); } LPZODIAC CParty::GetZodiac() { return m_pkZodiac; } void CParty::SetZodiac_for_Only_party(LPZODIAC pZodiac) { m_pkZodiac_for_Only_party = pZodiac; } LPZODIAC CParty::GetZodiac_for_Only_party() { return m_pkZodiac_for_Only_party; } #endif bool CParty::IsPositionNearLeader(LPCHARACTER ch) { if (!m_pkChrLeader) return false; if (DISTANCE_APPROX(ch->GetX() - m_pkChrLeader->GetX(), ch->GetY() - m_pkChrLeader->GetY()) >= PARTY_DEFAULT_RANGE) return false; return true; } int CParty::GetExpBonusPercent() { if (GetNearMemberCount() <= 1) return 0; return m_iExpBonus + m_iLongTimeExpBonus; } bool CParty::IsNearLeader(DWORD pid) { TMemberMap::iterator it = m_memberMap.find(pid); if (it == m_memberMap.end()) return false; return it->second.bNear; } BYTE CParty::CountMemberByVnum(DWORD dwVnum) { if (m_bPCParty) return 0; LPCHARACTER tch; BYTE bCount = 0; TMemberMap::iterator it; for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { if (!(tch = it->second.pCharacter)) continue; if (tch->IsPC()) continue; if (tch->GetMobTable().dwVnum == dwVnum) ++bCount; } return bCount; } void CParty::SendParameter(LPCHARACTER ch) { TPacketGCPartyParameter p; p.bHeader = HEADER_GC_PARTY_PARAMETER; p.bDistributeMode = m_iExpDistributionMode; LPDESC d = ch->GetDesc(); if (d) { d->Packet(&p, sizeof(TPacketGCPartyParameter)); } } void CParty::SendParameterToAll() { if (!m_bPCParty) return; TMemberMap::iterator it; for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) if (it->second.pCharacter) SendParameter(it->second.pCharacter); } void CParty::SetParameter(int iMode) { if (iMode >= PARTY_EXP_DISTRIBUTION_MAX_NUM) { sys_err("Invalid exp distribution mode %d", iMode); return; } m_iExpDistributionMode = iMode; SendParameterToAll(); } int CParty::GetExpDistributionMode() { return m_iExpDistributionMode; } void CParty::SetExpCentralizeCharacter(DWORD dwPID) { TMemberMap::iterator it = m_memberMap.find(dwPID); if (it == m_memberMap.end()) return; m_pkChrExpCentralize = it->second.pCharacter; } LPCHARACTER CParty::GetExpCentralizeCharacter() { return m_pkChrExpCentralize; } BYTE CParty::GetMemberMaxLevel() { BYTE bMax = 0; itertype(m_memberMap) it = m_memberMap.begin(); while (it!=m_memberMap.end()) { if (!it->second.bLevel) { ++it; continue; } if (!bMax) bMax = it->second.bLevel; else if (it->second.bLevel) bMax = MAX(bMax, it->second.bLevel); ++it; } return bMax; } BYTE CParty::GetMemberMinLevel() { BYTE bMin = PLAYER_MAX_LEVEL_CONST; itertype(m_memberMap) it = m_memberMap.begin(); while (it!=m_memberMap.end()) { if (!it->second.bLevel) { ++it; continue; } if (!bMin) bMin = it->second.bLevel; else if (it->second.bLevel) bMin = MIN(bMin, it->second.bLevel); ++it; } return bMin; } int CParty::ComputePartyBonusExpPercent() { if (GetNearMemberCount() <= 1) return 0; LPCHARACTER leader = GetLeaderCharacter(); int iBonusPartyExpFromItem = 0; // UPGRADE_PARTY_BONUS int iMemberCount=MIN(8, GetNearMemberCount()); if (leader && (leader->IsEquipUniqueItem(UNIQUE_ITEM_PARTY_BONUS_EXP) || leader->IsEquipUniqueItem(UNIQUE_ITEM_PARTY_BONUS_EXP_MALL) || leader->IsEquipUniqueItem(UNIQUE_ITEM_PARTY_BONUS_EXP_GIFT) || leader->IsEquipUniqueGroup(10010))) { // ءك±¹أّ ہ°µµ ہû؟ëہ» ب®ہخاط¾كار´ظ. if (g_iUseLocale) { iBonusPartyExpFromItem = 30; } else { iBonusPartyExpFromItem = KOR_aiUniqueItemPartyBonusExpPercentByMemberCount[iMemberCount]; } } if (g_iUseLocale) return iBonusPartyExpFromItem + CHN_aiPartyBonusExpPercentByMemberCount[iMemberCount]; else return iBonusPartyExpFromItem + KOR_aiPartyBonusExpPercentByMemberCount[iMemberCount]; // END_OF_UPGRADE_PARTY_BONUS } party.h Spoiler #ifndef __INC_METIN_II_GAME_PARTY_H__ #define __INC_METIN_II_GAME_PARTY_H__ #include "char.h" enum // unit : minute { PARTY_ENOUGH_MINUTE_FOR_EXP_BONUS = 60, // ئؤئ¼ °ل¼؛ بؤ 60؛ذ بؤ ؛خإح أك°، °واèؤ، ؛¸³ت½؛ PARTY_HEAL_COOLTIME_LONG = 60, PARTY_HEAL_COOLTIME_SHORT = 30, PARTY_MAX_MEMBER = 8, PARTY_DEFAULT_RANGE = 5000, }; enum EPartyRole { PARTY_ROLE_NORMAL, PARTY_ROLE_LEADER, PARTY_ROLE_ATTACKER, PARTY_ROLE_TANKER, PARTY_ROLE_BUFFER, PARTY_ROLE_SKILL_MASTER, PARTY_ROLE_HASTE, PARTY_ROLE_DEFENDER, PARTY_ROLE_MAX_NUM, }; enum EPartyExpDistributionModes { PARTY_EXP_DISTRIBUTION_NON_PARITY, PARTY_EXP_DISTRIBUTION_PARITY, PARTY_EXP_DISTRIBUTION_MAX_NUM }; class CParty; class CDungeon; #ifdef ENABLE_12ZI class CZodiac; #endif class CPartyManager : public singleton<CPartyManager> { public: typedef std::map<DWORD, LPPARTY> TPartyMap; typedef std::set<LPPARTY> TPCPartySet; public: CPartyManager(); virtual ~CPartyManager(); void Initialize(); //void SendPartyToDB(); void EnablePCParty() { m_bEnablePCParty = true; sys_log(0,"PARTY Enable"); } void DisablePCParty() { m_bEnablePCParty = false; sys_log(0,"PARTY Disable"); } bool IsEnablePCParty() { return m_bEnablePCParty; } LPPARTY CreateParty(LPCHARACTER pkLeader); void DeleteParty(LPPARTY pParty); void DeleteAllParty(); bool SetParty(LPCHARACTER pkChr); void SetPartyMember(DWORD dwPID, LPPARTY pParty); #ifdef ENABLE_PARTY_UPDATE void P2PLogin(DWORD pid, const char* name, long mapIdx, long channel); #else void P2PLogin(DWORD pid, const char* name); #endif void P2PLogout(DWORD pid); LPPARTY P2PCreateParty(DWORD pid); void P2PDeleteParty(DWORD pid); void P2PJoinParty(DWORD leader, DWORD pid, BYTE role = 0); void P2PQuitParty(DWORD pid); private: TPartyMap m_map_pkParty; // PID·خ ¾î´ہ ئؤئ¼؟، ہض³ھ °ث»ِاد±â ہ§ار ؤءإ×ہج³ت TPartyMap m_map_pkMobParty; // Mob ئؤئ¼´آ PID ´ë½إ VID ·خ µû·خ °ü¸®ار´ظ. TPCPartySet m_set_pkPCParty; // »ç¶÷µéہا ئؤئ¼ ہüأ¼ ءاص bool m_bEnablePCParty; // µً؛ٌ°، ؤرء®ہضءِ ¾تہ¸¸é »ç¶÷µéہا ئؤئ¼ »َإآ°، ؛¯°و؛ز°، }; enum EPartyMessages { PM_ATTACK, // Attack him PM_RETURN, // Return back to position PM_ATTACKED_BY, // I was attacked by someone PM_AGGRO_INCREASE, // My aggro is increased }; class CParty { public: typedef struct SMember { LPCHARACTER pCharacter; bool bNear; BYTE bRole; BYTE bLevel; std::string strName; #ifdef ENABLE_PARTY_UPDATE long mapIdx; long channel; #endif } TMember; typedef std::map<DWORD, TMember> TMemberMap; typedef std::map<std::string, int> TFlagMap; public: CParty(); virtual ~CParty(); void P2PJoin(DWORD dwPID); void P2PQuit(DWORD dwPID); virtual void Join(DWORD dwPID); void Quit(DWORD dwPID); void Link(LPCHARACTER pkChr); void Unlink(LPCHARACTER pkChr); void ChatPacketToAllMember(BYTE type, const char* format, ...); #ifdef ENABLE_PARTY_UPDATE void UpdateOnlineState(DWORD dwPID, const char* name, long mapIdx, long channel); #else void UpdateOnlineState(DWORD dwPID, const char* name); #endif void UpdateOfflineState(DWORD dwPID); DWORD GetLeaderPID(); LPCHARACTER GetLeaderCharacter(); LPCHARACTER GetLeader() { return m_pkChrLeader; } DWORD GetMemberCount(); DWORD GetNearMemberCount() { return m_iCountNearPartyMember; } bool IsMember(DWORD pid) { return m_memberMap.find(pid) != m_memberMap.end(); } bool IsNearLeader(DWORD pid); bool IsPositionNearLeader(LPCHARACTER ch); void SendMessage(LPCHARACTER ch, BYTE bMsg, DWORD dwArg1, DWORD dwArg2); void SendPartyJoinOneToAll(DWORD dwPID); void SendPartyJoinAllToOne(LPCHARACTER ch); void SendPartyRemoveOneToAll(DWORD dwPID); void SendPartyInfoOneToAll(DWORD pid); void SendPartyInfoOneToAll(LPCHARACTER ch); void SendPartyInfoAllToOne(LPCHARACTER ch); void SendPartyLinkOneToAll(LPCHARACTER ch); void SendPartyLinkAllToOne(LPCHARACTER ch); void SendPartyUnlinkOneToAll(LPCHARACTER ch); int GetPartyBonusExpPercent() { return m_iExpBonus; } int GetPartyBonusAttackGrade() { return m_iAttBonus; } int GetPartyBonusDefenseGrade() { return m_iDefBonus; } int ComputePartyBonusExpPercent(); inline int ComputePartyBonusAttackGrade(); inline int ComputePartyBonusDefenseGrade(); template <class Func> void ForEachMember(Func & f); template <class Func> void ForEachMemberPtr(Func & f); template <class Func> void ForEachOnlineMember(Func & f); template <class Func> void ForEachNearMember(Func & f); template <class Func> void ForEachOnMapMember (Func & f, long lMapIndex); template <class Func> bool ForEachOnMapMemberBool (Func & f, long lMapIndex); void Update(); int GetExpBonusPercent(); bool SetRole(DWORD pid, BYTE bRole, bool on); BYTE GetRole(DWORD pid); bool IsRole(DWORD pid, BYTE bRole); BYTE GetMemberMaxLevel(); BYTE GetMemberMinLevel(); void ComputeRolePoint(LPCHARACTER ch, BYTE bRole, bool bAdd); void HealParty(); void SummonToLeader(DWORD pid); void SetPCParty(bool b) { m_bPCParty = b; } LPCHARACTER GetNextOwnership(LPCHARACTER ch, long x, long y); void SetFlag(const std::string& name, int value); int GetFlag(const std::string& name); void SetDungeon(LPDUNGEON pDungeon); LPDUNGEON GetDungeon(); #ifdef ENABLE_12ZI void SetZodiac(LPZODIAC pZodiac); LPZODIAC GetZodiac(); #endif BYTE CountMemberByVnum(DWORD dwVnum); void SetParameter(int iMode); int GetExpDistributionMode(); void SetExpCentralizeCharacter(DWORD pid); LPCHARACTER GetExpCentralizeCharacter(); void RequestSetMemberLevel(DWORD pid, BYTE level); void P2PSetMemberLevel(DWORD pid, BYTE level); #ifdef ENABLE_PARTY_UPDATE void RequestSetMemberMapIndex(DWORD pid, long mapIdx); void P2PSetMemberMapIndex(DWORD pid, long mapIdx); void RequestSetMemberChannel(DWORD pid, long channel); void P2PSetMemberChannel(DWORD pid, long channel); #endif protected: void IncreaseOwnership(); virtual void Initialize(); void Destroy(); void RemovePartyBonus(); void RemoveBonus(); void RemoveBonusForOne(DWORD pid); void SendParameter(LPCHARACTER ch); void SendParameterToAll(); TMemberMap m_memberMap; DWORD m_dwLeaderPID; LPCHARACTER m_pkChrLeader; LPEVENT m_eventUpdate; TMemberMap::iterator m_itNextOwner; private: int m_iExpDistributionMode; LPCHARACTER m_pkChrExpCentralize; DWORD m_dwPartyStartTime; DWORD m_dwPartyHealTime; bool m_bPartyHealReady; bool m_bCanUsePartyHeal; int m_anRoleCount[PARTY_ROLE_MAX_NUM]; int m_anMaxRole[PARTY_ROLE_MAX_NUM]; int m_iLongTimeExpBonus; // used in Update int m_iLeadership; int m_iExpBonus; int m_iAttBonus; int m_iDefBonus; int m_iCountNearPartyMember; bool m_bPCParty; TFlagMap m_map_iFlag; LPDUNGEON m_pkDungeon; LPDUNGEON m_pkDungeon_for_Only_party; #ifdef ENABLE_12ZI LPZODIAC m_pkZodiac; LPZODIAC m_pkZodiac_for_Only_party; #endif public: void SetDungeon_for_Only_party(LPDUNGEON pDungeon); LPDUNGEON GetDungeon_for_Only_party(); #ifdef ENABLE_12ZI void SetZodiac_for_Only_party(LPZODIAC pZodiac); LPZODIAC GetZodiac_for_Only_party(); #endif }; template <class Func> void CParty::ForEachMember(Func & f) { TMemberMap::iterator it; for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) f(it->first); } template <class Func> void CParty::ForEachMemberPtr(Func & f) { TMemberMap::iterator it; for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) f(it->second.pCharacter); } template <class Func> void CParty::ForEachOnlineMember(Func & f) { TMemberMap::iterator it; for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) if (it->second.pCharacter) f(it->second.pCharacter); } template <class Func> void CParty::ForEachNearMember(Func & f) { TMemberMap::iterator it; for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) if (it->second.pCharacter && it->second.bNear) f(it->second.pCharacter); } template <class Func> void CParty::ForEachOnMapMember (Func & f, long lMapIndex) { TMemberMap::iterator it; for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { LPCHARACTER ch = it->second.pCharacter; if (ch) { if (ch->GetMapIndex () == lMapIndex) f(ch); } } } template <class Func> bool CParty::ForEachOnMapMemberBool(Func & f, long lMapIndex) { TMemberMap::iterator it; for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { LPCHARACTER ch = it->second.pCharacter; if (ch) { if (ch->GetMapIndex () == lMapIndex) { if(f(ch) == false) { return false; } } } } return true; } inline int CParty::ComputePartyBonusAttackGrade() { /* if (GetNearMemberCount() <= 1) return 0; int leadership = GetLeaderCharacter()->GetLeadershipSkillLevel(); int n = GetNearMemberCount(); if (n >= 3 && leadership >= 10) return 2; if (n >= 2 && leadership >= 4) return 1; */ return 0; } inline int CParty::ComputePartyBonusDefenseGrade() { /* if (GetNearMemberCount() <= 1) return 0; int leadership = GetLeaderCharacter()->GetLeadershipSkillLevel(); int n = GetNearMemberCount(); if (n >= 5 && leadership >= 24) return 2; if (n >= 4 && leadership >= 16) return 1; */ return 0; } #endif #ifdef ENABLE_ENABLE_DICE_SYSTEM #include "item.h" struct FPartyDropDiceRoll { const LPITEM m_itemDrop; LPCHARACTER m_itemOwner; int m_lastNumber; FPartyDropDiceRoll(const LPITEM itemDrop, LPCHARACTER itemOwner) : m_itemDrop(itemDrop), m_itemOwner(itemOwner), m_lastNumber(0) { }; void Process(const LPCHARACTER mobVictim) { if ((!mobVictim || (mobVictim->GetMobRank() >= MOB_RANK_BOSS && mobVictim->GetMobRank() <= MOB_RANK_KING)) && m_itemOwner->GetParty() && m_itemOwner->GetParty()->GetNearMemberCount() > 1) { LPPARTY pParty = m_itemOwner->GetParty(); pParty->ChatPacketToAllMember(CHAT_TYPE_DICE_INFO, LC_TEXT("*** Rolling for the following item: %16s ***"), m_itemDrop->GetName()); pParty->ForEachNearMember(*this); if (m_itemOwner) { m_itemDrop->SetOwnership(m_itemOwner); pParty->ChatPacketToAllMember(CHAT_TYPE_DICE_INFO, LC_TEXT("*** Rolling of %s: %16s ***"), m_itemDrop->GetName(), m_itemOwner->GetName()); } } else m_itemDrop->SetOwnership(m_itemOwner); } LPCHARACTER GetItemOwner() { return m_itemOwner; } const LPITEM GetItemDrop() { return m_itemDrop; } void operator () (LPCHARACTER ch) { if (!ch) return; LPPARTY pParty = ch->GetParty(); if (!pParty) return; while (true) { int pickedNumber = number(10000, 99999); if (pickedNumber > m_lastNumber) { m_lastNumber = pickedNumber; m_itemOwner = ch; } else if (pickedNumber == m_lastNumber) { continue; } else // if (pickedNumber < m_lastNumber) { } pParty->ChatPacketToAllMember(CHAT_TYPE_DICE_INFO, LC_TEXT("*** -> %16s - Dice score: %05d ***"), ch->GetName(), pickedNumber); break; } } }; #endif 1 1 1 2 Link to comment Share on other sites More sharing options...
Recommended Posts