Index: src/game/Guild.cpp =================================================================== --- src/game/Guild.cpp (working copy) +++ src/game/Guild.cpp (working copy) @@ -502,6 +502,9 @@ void Guild::CreateRank(std::string name,uint32 rights) { + if(m_ranks.size() >= GUILD_MAXRANKS) + return; + uint32 rank; QueryResult *result = sDatabase.PQuery( "SELECT MAX(`rid`) FROM `guild_rank` WHERE `guildid`='%u'",Id); @@ -649,10 +652,6 @@ data << itr->Class; data << itr->zoneId; data << (float(time(NULL)-logout_time) / DAY); - /*data << (uint8)0; - data << (uint8)1; - data << (uint8)1; - data << (uint8)1;*/ data << itr->Pnote; data << itr->OFFnote; } Index: src/game/Group.h =================================================================== --- src/game/Group.h (working copy) +++ src/game/Group.h (working copy) @@ -31,6 +31,7 @@ NOT_EMITED_YET = 3, NOT_VALID = 4 }; + enum GroupType { GROUPTYPE_NORMAL = 0, @@ -49,6 +50,7 @@ uint8 group; bool assistant; }; + struct Roll { Roll(): itemGUID(0), itemid(0), itemRandomPropId(0), totalPlayersRolling(0), totalNeed(0), totalGreed(0), totalPass(0), loot(NULL), itemSlot(0) {} @@ -69,9 +71,13 @@ Group() { m_leaderGuid = 0; + m_mainTank = 0; + m_mainAssistant =0; m_groupType = (GroupType)0; + m_bgGroup = false; m_lootMethod = (LootMethod)0; m_looterGuid = 0; + m_lootThreshold = (LootThreshold)2; for(int i=0; i=MAXGROUPSIZE) : (m_members.size()>=MAXRAIDSIZE); } bool isRaidGroup() { return (m_groupType==GROUPTYPE_RAID); } + bool isBGGroup() { return m_bgGroup; } const uint64& GetLeaderGUID() const { return m_leaderGuid; } LootMethod GetLootMethod() const { return m_lootMethod; } const uint64& GetLooterGuid() const { return m_looterGuid; } + LootThreshold GetLootThreshold() const { return m_lootThreshold; } // member manipulation methods bool IsMember(uint64 guid) const; @@ -137,6 +146,7 @@ _convertToRaid(); SendUpdate(); } + void SetBattlegroundGroup(const bool &state) { m_bgGroup = state; } void ChangeMembersGroup(const uint64 &guid, const uint8 &group) { if(!isRaidGroup()) @@ -144,18 +154,34 @@ if(_setMembersGroup(guid, group)) SendUpdate(); } - void ChangeAssistantFlag(const uint64 &guid, const bool &state) + void SetAssistant(const uint64 &guid, const bool &state) { if(!isRaidGroup()) return; if(_setAssistantFlag(guid, state)) SendUpdate(); } + void SetMainTank(const uint64 &guid) + { + if(!isRaidGroup()) + return; + + if(_setMainTank(guid)) + SendUpdate(); + } + void SetMainAssistant(const uint64 &guid) + { + if(!isRaidGroup()) + return; + + if(_setMainAssistant(guid)) + SendUpdate(); + } void SetTargetIcon(uint8 id, uint64 guid); // -no description- - void SendInit(WorldSession *session); + //void SendInit(WorldSession *session); void SendTargetIconList(WorldSession *session); void SendUpdate(); // ignore: GUID of player that will be ignored @@ -198,6 +224,8 @@ void _convertToRaid(); bool _setMembersGroup(const uint64 &guid, const uint8 &group); bool _setAssistantFlag(const uint64 &guid, const bool &state); + bool _setMainTank(const uint64 &guid); + bool _setMainAssistant(const uint64 &guid); int8 _getMemberIndex(uint64 Guid) const; @@ -205,9 +233,13 @@ vector m_invitees; uint64 m_leaderGuid; std::string m_leaderName; + uint64 m_mainTank; + uint64 m_mainAssistant; GroupType m_groupType; + bool m_bgGroup; uint64 m_targetIcons[TARGETICONCOUNT]; LootMethod m_lootMethod; + LootThreshold m_lootThreshold; uint64 m_looterGuid; vector RollId; }; Index: src/game/GroupHandler.cpp =================================================================== --- src/game/GroupHandler.cpp (working copy) +++ src/game/GroupHandler.cpp (working copy) @@ -308,8 +308,9 @@ return; uint32 lootMethod; + uint32 lootThreshold; uint64 lootMaster; - recv_data >> lootMethod >> lootMaster; + recv_data >> lootMethod >> lootMaster >> lootThreshold; Group *group = GetPlayer()->groupInfo.group; @@ -321,6 +322,7 @@ // everything's fine, do it group->SetLootMethod((LootMethod)lootMethod); group->SetLooterGuid(lootMaster); + group->SetLootThreshold((LootThreshold)lootThreshold); group->SendUpdate(); } @@ -477,7 +479,7 @@ group->ChangeMembersGroup(guid, groupNr); } -void WorldSession::HandleAssistantOpcode( WorldPacket & recv_data ) +void WorldSession::HandleGroupAssistantOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8+1); @@ -497,9 +499,33 @@ /********************/ // everything's fine, do it - group->ChangeAssistantFlag(guid, (flag==0?false:true)); + group->SetAssistant(guid, (flag==0?false:true)); } +void WorldSession::HandleGroupPromoteOpcode( WorldPacket & recv_data ) +{ + if(!GetPlayer()->groupInfo.group) + return; + + uint8 flag; + uint64 guid; + recv_data >> flag; + recv_data >> guid; + + Group *group = GetPlayer()->groupInfo.group; + + /** error handling **/ + if(!group->IsLeader(GetPlayer()->GetGUID())) + return; + /********************/ + + // everything's fine, do it + if(flag == 0) + group->SetMainTank(guid); + else if(flag == 1) + group->SetMainAssistant(guid); +} + void WorldSession::HandleRaidReadyCheckOpcode( WorldPacket & recv_data ) { if(!GetPlayer()->groupInfo.group) Index: src/game/Group.cpp =================================================================== --- src/game/Group.cpp (working copy) +++ src/game/Group.cpp (working copy) @@ -34,6 +34,7 @@ m_groupType = GROUPTYPE_NORMAL; m_lootMethod = GROUP_LOOT; + m_lootThreshold = UNCOMMON; AddMember(guid, name); @@ -41,7 +42,7 @@ sDatabase.BeginTransaction(); sDatabase.PExecute("DELETE FROM `group` WHERE `leaderGuid`='%u'", GUID_LOPART(m_leaderGuid)); sDatabase.PExecute("DELETE FROM `group_member` WHERE `leaderGuid`='%u'", GUID_LOPART(m_leaderGuid)); - sDatabase.PExecute("INSERT INTO `group`(`leaderGuid`,`lootMethod`,`looterGuid`,`icon1`,`icon2`,`icon3`,`icon4`,`icon5`,`icon6`,`icon7`,`icon8`,`isRaid`) VALUES('%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u',0)", GUID_LOPART(m_leaderGuid), m_lootMethod, GUID_LOPART(m_looterGuid), m_targetIcons[0], m_targetIcons[1], m_targetIcons[2], m_targetIcons[3], m_targetIcons[4], m_targetIcons[5], m_targetIcons[6], m_targetIcons[7]); + sDatabase.PExecute("INSERT INTO `group`(`leaderGuid`,`mainTank`,`mainAssistant`,`lootMethod`,`looterGuid`,`lootThreshold`,`icon1`,`icon2`,`icon3`,`icon4`,`icon5`,`icon6`,`icon7`,`icon8`,`isRaid`) VALUES('%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u',0)", GUID_LOPART(m_leaderGuid), GUID_LOPART(m_mainTank), GUID_LOPART(m_mainAssistant), m_lootMethod, GUID_LOPART(m_looterGuid), m_lootThreshold, m_targetIcons[0], m_targetIcons[1], m_targetIcons[2], m_targetIcons[3], m_targetIcons[4], m_targetIcons[5], m_targetIcons[6], m_targetIcons[7]); for(vector::const_iterator citr=m_members.begin(); citr!=m_members.end(); citr++) sDatabase.PExecute("INSERT INTO `group_member`(`leaderGuid`,`memberGuid`,`assistant`,`subgroup`) VALUES('%u','%u','%u','%u')", GUID_LOPART(m_leaderGuid), GUID_LOPART(citr->guid), (citr->assistant==1)?1:0, citr->group); @@ -50,19 +51,22 @@ void Group::LoadGroupFromDB(const uint64 &leaderGuid) { - // 0 1 2 3 4 5 6 7 8 9 10 - QueryResult *result = sDatabase.PQuery("SELECT `lootMethod`,`looterGuid`,`icon1`,`icon2`,`icon3`,`icon4`,`icon5`,`icon6`,`icon7`,`icon8`,`isRaid` FROM `group` WHERE `leaderGuid`='%u'", GUID_LOPART(leaderGuid)); + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + QueryResult *result = sDatabase.PQuery("SELECT `mainTank`,`mainAssistant`,`lootMethod`,`looterGuid`,`lootThreshold`,`icon1`,`icon2`,`icon3`,`icon4`,`icon5`,`icon6`,`icon7`,`icon8`,`isRaid` FROM `group` WHERE `leaderGuid`='%u'", GUID_LOPART(leaderGuid)); if(!result) return; m_leaderGuid = leaderGuid; objmgr.GetPlayerNameByGUID(m_leaderGuid, m_leaderName); - m_groupType = (*result)[10].GetBool() ? GROUPTYPE_RAID : GROUPTYPE_NORMAL; - m_lootMethod = (LootMethod)(*result)[0].GetUInt8(); - m_looterGuid = MAKE_GUID((*result)[1].GetUInt32(),HIGHGUID_PLAYER); + m_groupType = (*result)[13].GetBool() ? GROUPTYPE_RAID : GROUPTYPE_NORMAL; + m_mainTank = (*result)[0].GetUInt64(); + m_mainAssistant = (*result)[1].GetUInt64(); + m_lootMethod = (LootMethod)(*result)[2].GetUInt8(); + m_looterGuid = MAKE_GUID((*result)[3].GetUInt32(),HIGHGUID_PLAYER); + m_lootThreshold = (LootThreshold)(*result)[4].GetUInt16(); for(int i=0; iGetSession()->SendPacket(&data); } @@ -188,7 +192,7 @@ } data.Initialize(SMSG_GROUP_LIST, 14); - data<<(uint16)0<<(uint32)0<<(uint64)0; + data<<(uint16)0<<(uint8)0<<(uint32)0<<(uint64)0; player->GetSession()->SendPacket(&data); } RollId.clear(); @@ -308,7 +312,6 @@ void Group::GroupLoot(uint64 playerGUID, Loot *loot, Creature *creature) { - vector::iterator i; ItemPrototype const *item; uint8 itemSlot = 0; @@ -323,7 +326,7 @@ //sLog.outDebug("Group::GroupLoot: missing item prototype for item with id: %d", i->itemid); continue; } - if (item->Quality > ITEM_QUALITY_NORMAL) + if (item->Quality >= m_lootThreshold) { Roll r; uint32 newitemGUID = objmgr.GenerateLowGuid(HIGHGUID_ITEM); @@ -370,7 +373,7 @@ for (i=loot->items.begin(); i != loot->items.end(); i++) { item = objmgr.GetItemPrototype(i->itemid); - if (item->Quality > ITEM_QUALITY_NORMAL) + if (item->Quality >= m_lootThreshold) { Roll r; uint32 newitemGUID = objmgr.GenerateLowGuid(HIGHGUID_ITEM); @@ -622,7 +625,7 @@ return count; } -void Group::SendInit(WorldSession *session) +/*void Group::SendInit(WorldSession *session) { if(!session) return; @@ -639,6 +642,7 @@ // guess size WorldPacket data(SMSG_GROUP_LIST, (2+4+8+8+1+2+m_members.size()*20)); data << (uint8)m_groupType; + data << (uint8)0;// 2.0.x, may be wrong position data << (uint8)myFlag; int count = 0; @@ -662,10 +666,11 @@ data << (uint8)m_lootMethod; data << m_looterGuid; data << (uint16)2; - + data << m_mainTank;//2.0.x + data << m_mainAssistant;//2.0.x session->SendPacket( &data ); } -} +}*/ void Group::SendTargetIconList(WorldSession *session) { @@ -690,7 +695,6 @@ void Group::SendUpdate() { Player *player; - WorldPacket data; for(vector::const_iterator citr=m_members.begin(); citr!=m_members.end(); citr++) { @@ -699,8 +703,9 @@ continue; // guess size - data.Initialize(SMSG_GROUP_LIST, (6+8+8+1+2+m_members.size()*20)); + WorldPacket data(SMSG_GROUP_LIST, (6+8+8+1+2+m_members.size()*20)); data << (uint8)m_groupType; + data << (uint8)((m_bgGroup==true) ? 1 : 0);//2.0.x // own flags (groupid | (assistant?0x80:0)) data << (uint8)(citr->group | (citr->assistant?0x80:0)); @@ -721,7 +726,9 @@ data << m_leaderGuid; data << (uint8)m_lootMethod; data << m_looterGuid; - data << (uint16)2; + data << (uint16)m_lootThreshold; // loot threshold + data << m_mainTank;//2.0.x + data << m_mainAssistant;//2.0.x player->GetSession()->SendPacket( &data ); } @@ -956,6 +963,30 @@ return true; } +bool Group::_setMainTank(const uint64 &guid) +{ + if(guid != 0 && _getMemberIndex(guid) < 0) + return false; + + if(m_mainAssistant == guid) + _setMainAssistant(0); + m_mainTank = guid; + sDatabase.PExecute("UPDATE `group` SET `mainTank`='%u' WHERE `leaderGuid`='%u'", GUID_LOPART(m_mainTank), GUID_LOPART(m_leaderGuid)); + return true; +} + +bool Group::_setMainAssistant(const uint64 &guid) +{ + if(guid != 0 && _getMemberIndex(guid) < 0) + return false; + + if(m_mainTank == guid) + _setMainTank(0); + m_mainAssistant = guid; + sDatabase.PExecute("UPDATE `group` SET `mainAssistant`='%u' WHERE `leaderGuid`='%u'", GUID_LOPART(m_mainAssistant), GUID_LOPART(m_leaderGuid)); + return true; +} + int8 Group::_getMemberIndex(uint64 Guid) const { for (int i=0; iModifyMoney( -(int32)price ); Item *charter = _player->StoreNewItem( dest, GUILD_CHARTER_ITEM_ID, 1, true ); + if(!charter) + return; charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT, charter->GetGUIDLow()); charter->SetState(ITEM_CHANGED, _player); _player->SendNewItem(charter, 1, true, false); @@ -127,6 +129,7 @@ void WorldSession::HandlePetitionShowSignOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8); + recv_data.hexlike(); //sLog.outDebug("Received opcode CMSG_PETITION_SHOW_SIGNATURES"); if(_player->GetGuildId()) @@ -178,6 +181,7 @@ void WorldSession::HandlePetitionQueryOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,4+8); + recv_data.hexlike(); sLog.outDebug("Received opcode CMSG_PETITION_QUERY"); uint32 guildguid; @@ -195,9 +199,10 @@ std::string guildname = "NO_GUILD_NAME_FOR_GUID"; uint8 signs = 0; + // todo: check this packet unsigned char tdata[51] = { - 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; QueryResult *result = sDatabase.PQuery( @@ -230,6 +235,7 @@ void WorldSession::HandlePetitionRenameOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8+1); + recv_data.hexlike(); //sLog.outDebug("Received opcode MSG_PETITION_RENAME"); @@ -265,6 +271,7 @@ void WorldSession::HandlePetitionSignOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8); + recv_data.hexlike(); //sLog.outDebug("Received opcode CMSG_PETITION_SIGN"); Field *fields; @@ -325,6 +332,7 @@ void WorldSession::HandlePetitionDeclineOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8); + recv_data.hexlike(); //sLog.outDebug("Received opcode MSG_PETITION_DECLINE"); @@ -352,13 +360,16 @@ void WorldSession::HandleOfferPetitionOpcode( WorldPacket & recv_data ) { - CHECK_PACKET_SIZE(recv_data,8+8); + CHECK_PACKET_SIZE(recv_data,4+8+8); + recv_data.hexlike(); // todo: check this packet... //sLog.outDebug("Received opcode CMSG_OFFER_PETITION"); uint8 signs = 0; uint64 petitionguid, plguid; + uint32 petitiontype = 0; // 0 - guild, 1 - arena? Player *player; + recv_data >> petitiontype; // 2.0.8 - petition type? recv_data >> petitionguid; // petition guid recv_data >> plguid; // player guid sLog.outDebug("OFFER PETITION: GUID1 %u, to player id: %u", GUID_LOPART(petitionguid), GUID_LOPART(plguid)); @@ -409,11 +420,8 @@ void WorldSession::HandleTurnInPetitionOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8); + recv_data.hexlike(); - /* - don't know how to cause this opcode, it is possible that charter-party has wrong properties \flags (are not present even names)... - Here it is necessary to receive number of signatures, to compare with 9 and if it is equal - if guild, to add the players who have signed charter in guild, to remove charter-party and to send the answer... - Still is any interesting opcode UMSG_DELETE_GUILD_CHARTER:)*/ //sLog.outDebug("Received opcode CMSG_TURN_IN_PETITION"); WorldPacket data; uint64 petitionguid; @@ -525,14 +533,14 @@ void WorldSession::HandlePetitionShowListOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8); + recv_data.hexlike(); - WorldPacket data; uint64 guid; // TODO: WHY STATIC?????????????? - unsigned char tdata[21] = + unsigned char tdata[25] = { - 0x01, 0x01, 0x00, 0x00, 0x00, 0xe7, 0x16, 0x00, 0x00, 0xef, 0x23, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 + 0x01, 0x01, 0x00, 0x00, 0x00, 0xe7, 0x16, 0x00, 0x00, 0x21, 0x3f, 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00 }; recv_data >> guid; @@ -543,7 +551,7 @@ return; } - data.Initialize( SMSG_PETITION_SHOWLIST, (8+sizeof(tdata)) ); + WorldPacket data( SMSG_PETITION_SHOWLIST, (8+sizeof(tdata)) ); data << guid; data.append( tdata, sizeof(tdata) ); SendPacket( &data ); @@ -1309,7 +1317,7 @@ return; } - if(guild->GetNrRanks() >= 10) // cleint not let create more 10 ranks + if(guild->GetNrRanks() >= 10) // client not let create more 10 ranks return; recvPacket >> rankname;