diff options
author | n0n4m3 <none@none> | 2010-04-11 11:16:42 +0400 |
---|---|---|
committer | n0n4m3 <none@none> | 2010-04-11 11:16:42 +0400 |
commit | be95faff2370db63eedd812ab4e70bb87e34b570 (patch) | |
tree | d2db46e9e6161abe0dd8740461979b8309ef79c7 | |
parent | 457df07bd4fd1b394cfcdbb63d5ff76e87fe8c89 (diff) |
Fix mail, professions, group loot, console spam, and some fixes. Big thx to TOM_RUS.
--HG--
branch : trunk
34 files changed, 303 insertions, 300 deletions
diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index ea1d73b67ee..ddcd1b35d79 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -1813,9 +1813,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) } } - uint32 itemTextId = objmgr.CreateItemText(text); - - MailDraft draft(subject, itemTextId); + MailDraft draft(subject, text); if (item) { diff --git a/src/game/AuctionHouseHandler.cpp b/src/game/AuctionHouseHandler.cpp index c73e00cdb28..586319a2e74 100644 --- a/src/game/AuctionHouseHandler.cpp +++ b/src/game/AuctionHouseHandler.cpp @@ -128,7 +128,7 @@ void WorldSession::SendAuctionOutbiddedMail(AuctionEntry *auction, uint32 newPri if (oldBidder || oldBidder_accId) { std::ostringstream msgAuctionOutbiddedSubject; - msgAuctionOutbiddedSubject << auction->item_template << ":0:" << AUCTION_OUTBIDDED; + msgAuctionOutbiddedSubject << auction->item_template << ":0:" << AUCTION_OUTBIDDED << ":0:0"; if (oldBidder && !_player) oldBidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, auctionbot.GetAHBplayerGUID(), newPrice, auction->GetAuctionOutBid(), auction->item_template); @@ -136,7 +136,7 @@ void WorldSession::SendAuctionOutbiddedMail(AuctionEntry *auction, uint32 newPri if (oldBidder && _player) oldBidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, _player->GetGUID(), newPrice, auction->GetAuctionOutBid(), auction->item_template); - MailDraft(msgAuctionOutbiddedSubject.str()) + MailDraft(msgAuctionOutbiddedSubject.str(), "") // TODO: fix body .AddMoney(auction->bid) .SendMailTo(MailReceiver(oldBidder, auction->bidder), auction); } @@ -156,9 +156,9 @@ void WorldSession::SendAuctionCancelledToBidderMail(AuctionEntry* auction) if (bidder || bidder_accId) { std::ostringstream msgAuctionCancelledSubject; - msgAuctionCancelledSubject << auction->item_template << ":0:" << AUCTION_CANCELLED_TO_BIDDER; + msgAuctionCancelledSubject << auction->item_template << ":0:" << AUCTION_CANCELLED_TO_BIDDER << ":0:0"; - MailDraft(msgAuctionCancelledSubject.str()) + MailDraft(msgAuctionCancelledSubject.str(), "") // TODO: fix body .AddMoney(auction->bid) .SendMailTo(MailReceiver(bidder, auction->bidder), auction); } @@ -457,10 +457,10 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket & recv_data) } // Return the item by mail std::ostringstream msgAuctionCanceledOwner; - msgAuctionCanceledOwner << auction->item_template << ":0:" << AUCTION_CANCELED; + msgAuctionCanceledOwner << auction->item_template << ":0:" << AUCTION_CANCELED << ":0:0"; // item will deleted or added to received mail list - MailDraft(msgAuctionCanceledOwner.str()) + MailDraft(msgAuctionCanceledOwner.str(), "") // TODO: fix body .AddItem(pItem) .SendMailTo(pl, auction); } diff --git a/src/game/AuctionHouseMgr.cpp b/src/game/AuctionHouseMgr.cpp index 282836a76b2..1f952e249c3 100644 --- a/src/game/AuctionHouseMgr.cpp +++ b/src/game/AuctionHouseMgr.cpp @@ -152,9 +152,6 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry *auction) msgAuctionWonBody << std::dec << ":" << auction->bid << ":" << auction->buyout; sLog.outDebug("AuctionWon body string : %s", msgAuctionWonBody.str().c_str()); - //prepare mail data... : - uint32 itemTextId = objmgr.CreateItemText(msgAuctionWonBody.str()); - // set owner to bidder (to prevent delete item with sender char deleting) // owner in `data` will set at mail receive and item extracting CharacterDatabase.PExecute("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'",auction->bidder,pItem->GetGUIDLow()); @@ -163,9 +160,9 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry *auction) if (bidder) bidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, bidder_guid, 0, 0, auction->item_template); - MailDraft(msgAuctionWonSubject.str(), itemTextId) + MailDraft(msgAuctionWonSubject.str(), msgAuctionWonBody.str()) .AddItem(pItem) - .SendMailTo(MailReceiver(bidder,auction->bidder), auction, MAIL_CHECK_MASK_AUCTION); + .SendMailTo(MailReceiver(bidder,auction->bidder), MailSender(auction), MAIL_CHECK_MASK_NONE); } } @@ -193,10 +190,8 @@ void AuctionHouseMgr::SendAuctionSalePendingMail(AuctionEntry * auction) sLog.outDebug("AuctionSalePending body string : %s", msgAuctionSalePendingBody.str().c_str()); - uint32 itemTextId = objmgr.CreateItemText(msgAuctionSalePendingBody.str()); - - MailDraft(msgAuctionSalePendingSubject.str(), itemTextId) - .SendMailTo(MailReceiver(owner,auction->owner), auction, MAIL_CHECK_MASK_AUCTION); + MailDraft(msgAuctionSalePendingSubject.str(), msgAuctionSalePendingBody.str()) + .SendMailTo(MailReceiver(owner,auction->owner), auction, MAIL_CHECK_MASK_NONE); } } @@ -222,8 +217,6 @@ void AuctionHouseMgr::SendAuctionSuccessfulMail(AuctionEntry * auction) sLog.outDebug("AuctionSuccessful body string : %s", auctionSuccessfulBody.str().c_str()); - uint32 itemTextId = objmgr.CreateItemText(auctionSuccessfulBody.str()); - uint32 profit = auction->bid + auction->deposit - auctionCut; //FIXME: what do if owner offline @@ -233,9 +226,9 @@ void AuctionHouseMgr::SendAuctionSuccessfulMail(AuctionEntry * auction) //send auction owner notification, bidder must be current! owner->GetSession()->SendAuctionOwnerNotification(auction); } - MailDraft(msgAuctionSuccessfulSubject.str(), itemTextId) + MailDraft(msgAuctionSuccessfulSubject.str(), auctionSuccessfulBody.str()) .AddMoney(profit) - .SendMailTo(MailReceiver(owner,auction->owner), auction, MAIL_CHECK_MASK_AUCTION, sWorld.getConfig(CONFIG_MAIL_DELIVERY_DELAY)); + .SendMailTo(MailReceiver(owner,auction->owner), auction, MAIL_CHECK_MASK_NONE, sWorld.getConfig(CONFIG_MAIL_DELIVERY_DELAY)); } } @@ -253,12 +246,12 @@ void AuctionHouseMgr::SendAuctionExpiredMail(AuctionEntry * auction) if (owner || owner_accId) { std::ostringstream subject; - subject << auction->item_template << ":0:" << AUCTION_EXPIRED; + subject << auction->item_template << ":0:" << AUCTION_EXPIRED << ":0:0"; if (owner && owner->GetGUIDLow() != auctionbot.GetAHBplayerGUID()) owner->GetSession()->SendAuctionOwnerNotification(auction); - MailDraft(subject.str()) + MailDraft(subject.str(), "") // TODO: fix body .AddItem(pItem) .SendMailTo(MailReceiver(owner,auction->owner), auction); } diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 6e538efd858..fbba3cc89ec 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -954,10 +954,9 @@ void BattleGround::SendRewardMarkByMail(Player *plr,uint32 mark, uint32 count) // text std::string textFormat = plr->GetSession()->GetTrinityString(LANG_BG_MARK_BY_MAIL); char textBuf[300]; - snprintf(textBuf,300,textFormat.c_str(),GetName(),GetName()); - uint32 itemTextId = objmgr.CreateItemText(textBuf); + snprintf(textBuf, 300, textFormat.c_str(), GetName(), GetName()); - MailDraft(subject, itemTextId) + MailDraft(subject, textBuf) .AddItem(markItem) .SendMailTo(plr, MailSender(MAIL_CREATURE, bmEntry)); } diff --git a/src/game/Group.cpp b/src/game/Group.cpp index c06833354e6..de03527da31 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -470,10 +470,11 @@ void Group::Disband(bool hideDestroy) /*** LOOT SYSTEM ***/ /*********************************************************/ -void Group::SendLootStartRoll(uint32 CountDown, const Roll &r) +void Group::SendLootStartRoll(uint32 CountDown, uint32 mapid, const Roll &r) { WorldPacket data(SMSG_LOOT_START_ROLL, (8+4+4+4+4+4+4+1)); data << uint64(r.itemGUID); // guid of rolled item + data << uint32(mapid); // 3.3.3 mapid data << uint32(r.totalPlayersRolling); // maybe the number of players rolling for it??? data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for data << uint32(r.itemRandomSuffix); // randomSuffix @@ -504,7 +505,7 @@ void Group::SendLootRoll(const uint64& SourceGuid, const uint64& TargetGuid, uin data << uint32(r.itemRandomPropId); // Item random property ID data << uint8(RollNumber); // 0: "Need for: [item name]" > 127: "you passed on: [item name]" Roll number data << uint8(RollType); // 0: "Need for: [item name]" 0: "You have selected need for [item name] 1: need roll 2: greed roll - data << uint8(0); // 2.4.0 + data << uint8(0); // auto pass on loot for (Roll::PlayerVote::const_iterator itr=r.playerVote.begin(); itr != r.playerVote.end(); ++itr) { @@ -624,7 +625,8 @@ void Group::GroupLoot(Loot *loot, WorldObject* pLootedObject) loot->items[itemSlot].is_blocked = true; - SendLootStartRoll(60000, *r); + Creature *creature; + SendLootStartRoll(60000, creature->GetMapId(), *r); RollId.push_back(r); @@ -689,7 +691,8 @@ void Group::NeedBeforeGreed(Loot *loot, WorldObject* pLootedObject) loot->items[itemSlot].is_blocked = true; - SendLootStartRoll(60000, *r); + Creature *creature; + SendLootStartRoll(60000, creature->GetMapId(), *r); RollId.push_back(r); @@ -726,7 +729,7 @@ void Group::MasterLoot(Loot* /*loot*/, WorldObject* pLootedObject) if (looter->IsWithinDistInMap(pLootedObject,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false)) { - data << looter->GetGUID(); + data << uint64(looter->GetGUID()); ++real_count; } } @@ -1096,8 +1099,8 @@ void Group::OfflineReadyCheck() if (!pl || !pl->GetSession()) { WorldPacket data(MSG_RAID_READY_CHECK_CONFIRM, 9); - data << citr->guid; - data << (uint8)0; + data << uint64(citr->guid); + data << uint8(0); BroadcastReadyCheck(&data); } } diff --git a/src/game/Group.h b/src/game/Group.h index 8d606cd7f01..052f8c970b8 100644 --- a/src/game/Group.h +++ b/src/game/Group.h @@ -320,7 +320,7 @@ class Group /*** LOOT SYSTEM ***/ /*********************************************************/ - void SendLootStartRoll(uint32 CountDown, const Roll &r); + void SendLootStartRoll(uint32 CountDown, uint32 mapid, const Roll &r); void SendLootRoll(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); void SendLootRollWon(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); void SendLootAllPassed(uint32 NumberOfPlayers, const Roll &r); diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp index 1d6aae6f095..404b66f1a3f 100644 --- a/src/game/GroupHandler.cpp +++ b/src/game/GroupHandler.cpp @@ -241,6 +241,7 @@ void WorldSession::HandleGroupUninviteGuidOpcode(WorldPacket & recv_data) { uint64 guid; recv_data >> guid; + recv_data.read_skip<uint8>(); //can't uninvite yourself if (guid == GetPlayer()->GetGUID()) @@ -616,8 +617,8 @@ void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket & recv_data) // everything's fine, do it WorldPacket data(MSG_RAID_READY_CHECK_CONFIRM, 9); - data << GetPlayer()->GetGUID(); - data << state; + data << uint64(GetPlayer()->GetGUID()); + data << uint8(state); group->BroadcastReadyCheck(&data); } } diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp index 0b150358896..48901452cb4 100644 --- a/src/game/GuildHandler.cpp +++ b/src/game/GuildHandler.cpp @@ -42,7 +42,7 @@ void WorldSession::HandleGuildQueryOpcode(WorldPacket& recvPacket) return; } - ERR_GUILD_PLAYER_NOT_IN_GUILD); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); } void WorldSession::HandleGuildCreateOpcode(WorldPacket& recvPacket) @@ -79,14 +79,14 @@ void WorldSession::HandleGuildInviteOpcode(WorldPacket& recvPacket) if (!player) { - SendGuildCommandResult(GUILD_INVITE_S, Invitedname, GUILD_PLAYER_NOT_FOUND); + SendGuildCommandResult(GUILD_INVITE_S, Invitedname, ERR_GUILD_PLAYER_NOT_FOUND_S); return; } Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if (!guild) { - ERR_GUILD_PLAYER_NOT_IN_GUILD); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); return; } @@ -148,7 +148,7 @@ void WorldSession::HandleGuildRemoveOpcode(WorldPacket& recvPacket) Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if (!guild) { - ERR_GUILD_PLAYER_NOT_IN_GUILD); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); return; } @@ -227,7 +227,7 @@ void WorldSession::HandleGuildInfoOpcode(WorldPacket& /*recvPacket*/) guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if (!guild) { - ERR_GUILD_PLAYER_NOT_IN_GUILD); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); return; } @@ -261,7 +261,7 @@ void WorldSession::HandleGuildPromoteOpcode(WorldPacket& recvPacket) Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if (!guild) { - ERR_GUILD_PLAYER_NOT_IN_GUILD); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); return; } @@ -318,7 +318,7 @@ void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket) if (!guild) { - ERR_GUILD_PLAYER_NOT_IN_GUILD); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); return; } @@ -373,7 +373,7 @@ void WorldSession::HandleGuildLeaveOpcode(WorldPacket& /*recvPacket*/) Guild *guild = objmgr.GetGuildById(_player->GetGuildId()); if (!guild) { - ERR_GUILD_PLAYER_NOT_IN_GUILD); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); return; } @@ -405,7 +405,7 @@ void WorldSession::HandleGuildDisbandOpcode(WorldPacket& /*recvPacket*/) Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if (!guild) { - ERR_GUILD_PLAYER_NOT_IN_GUILD); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); return; } @@ -436,7 +436,7 @@ void WorldSession::HandleGuildLeaderOpcode(WorldPacket& recvPacket) if (!guild) { - ERR_GUILD_PLAYER_NOT_IN_GUILD); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); return; } @@ -451,7 +451,7 @@ void WorldSession::HandleGuildLeaderOpcode(WorldPacket& recvPacket) if (!slot) { - SendGuildCommandResult(GUILD_INVITE_S, name, GUILD_PLAYER_NOT_IN_GUILD_S); + SendGuildCommandResult(GUILD_INVITE_S, name, ERR_GUILD_PLAYER_NOT_IN_GUILD_S); return; } @@ -475,7 +475,7 @@ void WorldSession::HandleGuildMOTDOpcode(WorldPacket& recvPacket) Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if (!guild) { - ERR_GUILD_PLAYER_NOT_IN_GUILD); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); return; } @@ -503,7 +503,7 @@ void WorldSession::HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket) Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if (!guild) { - ERR_GUILD_PLAYER_NOT_IN_GUILD); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); return; } @@ -518,7 +518,7 @@ void WorldSession::HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket) if (!slot) { - SendGuildCommandResult(GUILD_INVITE_S, name, GUILD_PLAYER_NOT_IN_GUILD_S); + SendGuildCommandResult(GUILD_INVITE_S, name, ERR_GUILD_PLAYER_NOT_IN_GUILD_S); return; } @@ -541,7 +541,7 @@ void WorldSession::HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket) Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if (!guild) { - ERR_GUILD_PLAYER_NOT_IN_GUILD); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); return; } @@ -578,7 +578,7 @@ void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket) if (!guild) { recvPacket.rpos(recvPacket.wpos()); // set to end to avoid warnings spam - ERR_GUILD_PLAYER_NOT_IN_GUILD); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); return; } else if (GetPlayer()->GetGUID() != guild->GetLeader()) @@ -627,7 +627,7 @@ void WorldSession::HandleGuildAddRankOpcode(WorldPacket& recvPacket) Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if (!guild) { - ERR_GUILD_PLAYER_NOT_IN_GUILD); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); return; } @@ -653,7 +653,7 @@ void WorldSession::HandleGuildDelRankOpcode(WorldPacket& /*recvPacket*/) Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if (!guild) { - ERR_GUILD_PLAYER_NOT_IN_GUILD); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); return; } else if (GetPlayer()->GetGUID() != guild->GetLeader()) @@ -690,13 +690,13 @@ void WorldSession::HandleGuildChangeInfoTextOpcode(WorldPacket& recvPacket) Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if (!guild) { - ERR_GUILD_PLAYER_NOT_IN_GUILD); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); return; } if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_MODIFY_GUILD_INFO)) { - SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PERMISSIONS); + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PERMISSIONS); return; } diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h index a22078243f2..7cec4551a5a 100644 --- a/src/game/ItemPrototype.h +++ b/src/game/ItemPrototype.h @@ -118,6 +118,7 @@ enum ITEM_FLAGS ITEM_FLAGS_REFUNDABLE = 0x00001000, // item cost can be refunded within 2 hours after purchase ITEM_FLAGS_CHARTER = 0x00002000, // arena/guild charter ITEM_FLAGS_REFUNDABLE_2 = 0x00008000, + ITEM_FLAGS_UNK1 = 0x00010000, ITEM_FLAGS_PROSPECTABLE = 0x00040000, ITEM_FLAGS_UNIQUE_EQUIPPED = 0x00080000, ITEM_FLAGS_USEABLE_IN_ARENA = 0x00200000, diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 5873a72ca83..07c0278b634 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -2408,9 +2408,7 @@ bool ChatHandler::HandleSendMailCommand(const char* args) // from console show not existed sender MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); - uint32 itemTextId = !text.empty() ? objmgr.CreateItemText(text) : 0; - - MailDraft(subject, itemTextId) + MailDraft(subject, text) .SendMailTo(MailReceiver(target,GUID_LOPART(target_guid)),sender); std::string nameLink = playerLink(target_name); diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 3fb48cc3de9..3ca0787c666 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -3630,7 +3630,7 @@ void ChatHandler::HandleLearnSkillRecipesHelper(Player* player,uint32 skill_id) if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,player,false)) continue; - player->learnSpell(skillLine->spellId,false); + player->learnSpell(skillLine->spellId, false); } } @@ -3728,7 +3728,7 @@ bool ChatHandler::HandleLearnAllRecipesCommand(const char* args) HandleLearnSkillRecipesHelper(target,targetSkillInfo->id); uint16 maxLevel = target->GetPureMaxSkillValue(targetSkillInfo->id); - target->SetSkill(targetSkillInfo->id, maxLevel, maxLevel); + target->SetSkill(targetSkillInfo->id, target->GetSkillStep(targetSkillInfo->id), maxLevel, maxLevel); PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str()); return true; } diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index ce811cd6fa6..6c616522a1e 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -1629,7 +1629,7 @@ bool ChatHandler::HandleSetSkillCommand(const char *args) if (level <= 0 || level > max || max <= 0) return false; - target->SetSkill(skill, level, max); + target->SetSkill(skill, target->GetSkillStep(skill), level, max); PSendSysMessage(LANG_SET_SKILL, skill, sl->name[GetSessionDbcLocale()], tNameLink.c_str(), level, max); return true; @@ -2325,7 +2325,7 @@ bool ChatHandler::HandleLearnAllCommand(const char* /*args*/) continue; } - m_session->GetPlayer()->learnSpell(spell,false); + m_session->GetPlayer()->learnSpell(spell, false); } SendSysMessage(LANG_COMMAND_LEARN_MANY_SPELLS); @@ -2365,7 +2365,7 @@ bool ChatHandler::HandleLearnAllGMCommand(const char* /*args*/) continue; } - m_session->GetPlayer()->learnSpell(spell,false); + m_session->GetPlayer()->learnSpell(spell, false); } SendSysMessage(LANG_LEARNING_GM_SKILLS); @@ -2413,7 +2413,7 @@ bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/) if (!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) continue; - m_session->GetPlayer()->learnSpell(i,false); + m_session->GetPlayer()->learnSpell(i, false); } SendSysMessage(LANG_COMMAND_LEARN_CLASS_SPELLS); @@ -2549,7 +2549,7 @@ bool ChatHandler::HandleLearnAllLangCommand(const char* /*args*/) { // skipping UNIVERSAL language (0) for (uint8 i = 1; i < LANGUAGES_COUNT; ++i) - m_session->GetPlayer()->learnSpell(lang_description[i].spell_id,false); + m_session->GetPlayer()->learnSpell(lang_description[i].spell_id, false); SendSysMessage(LANG_COMMAND_LEARN_ALL_LANG); return true; @@ -2608,7 +2608,7 @@ bool ChatHandler::HandleLearnCommand(const char *args) if (allRanks) targetPlayer->learnSpellHighRank(spell); else - targetPlayer->learnSpell(spell,false); + targetPlayer->learnSpell(spell, false); uint32 first_spell = spellmgr.GetFirstSpellInChain(spell); if (GetTalentSpellCost(first_spell)) @@ -7067,10 +7067,8 @@ bool ChatHandler::HandleSendItemsCommand(const char *args) // from console show not existed sender MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); - uint32 itemTextId = !text.empty() ? objmgr.CreateItemText(text) : 0; - // fill mail - MailDraft draft(subject, itemTextId); + MailDraft draft(subject, text); for (ItemPairs::const_iterator itr = items.begin(); itr != items.end(); ++itr) { @@ -7127,9 +7125,7 @@ bool ChatHandler::HandleSendMoneyCommand(const char *args) // from console show not existed sender MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); - uint32 itemTextId = !text.empty() ? objmgr.CreateItemText(text) : 0; - - MailDraft(subject, itemTextId) + MailDraft(subject, text) .AddMoney(money) .SendMailTo(MailReceiver(receiver,GUID_LOPART(receiver_guid)),sender); diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp index 448a90cd582..a552664d162 100644 --- a/src/game/Mail.cpp +++ b/src/game/Mail.cpp @@ -225,14 +225,12 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) pl->SendMailResult(0, MAIL_SEND, MAIL_OK); - uint32 itemTextId = !body.empty() ? objmgr.CreateItemText(body) : 0; - pl->ModifyMoney(-int32(reqmoney)); pl->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost); bool needItemDelay = false; - MailDraft draft(subject, itemTextId); + MailDraft draft(subject, body); if (items_count > 0 || money > 0) { @@ -276,7 +274,7 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) draft .AddMoney(money) .AddCOD(COD) - .SendMailTo(MailReceiver(receive, GUID_LOPART(rc)), pl, MAIL_CHECK_MASK_NONE, deliver_delay); + .SendMailTo(MailReceiver(receive, GUID_LOPART(rc)), MailSender(pl), body.empty() ? MailCheckMask(MAIL_CHECK_MASK_NONE | MAIL_CHECK_MASK_COPIED) : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); CharacterDatabase.BeginTransaction(); pl->SaveInventoryAndGoldToDB(); @@ -301,7 +299,6 @@ void WorldSession::HandleMailMarkAsRead(WorldPacket & recv_data) if (pl->unReadMails) --pl->unReadMails; m->checked = m->checked | MAIL_CHECK_MASK_READ; - // m->expire_time = time(NULL) + (30 * DAY); // Expire time do not change at reading mail pl->m_mailsUpdated = true; m->state = MAIL_STATE_CHANGED; } @@ -366,7 +363,7 @@ void WorldSession::HandleMailReturnToSender(WorldPacket & recv_data) // send back only to players and simple drop for other cases if (m->messageType == MAIL_NORMAL) { - MailDraft draft(m->subject, m->itemTextId); + MailDraft draft(m->subject, m->body); if (m->mailTemplateId) draft = MailDraft(m->mailTemplateId, false); // items already included @@ -465,9 +462,9 @@ void WorldSession::HandleMailTakeItem(WorldPacket & recv_data) // check player existence if (receive || sender_accId) { - MailDraft(m->subject) + MailDraft(m->subject, "") .AddMoney(m->COD) - .SendMailTo(MailReceiver(receive,m->sender),MailSender(MAIL_NORMAL,m->receiver), MAIL_CHECK_MASK_COD_PAYMENT); + .SendMailTo(MailReceiver(receive, m->sender), MailSender(MAIL_NORMAL, m->receiver), MAIL_CHECK_MASK_COD_PAYMENT); } pl->ModifyMoney(-int32(m->COD)); @@ -565,7 +562,7 @@ void WorldSession::HandleGetMailList(WorldPacket & recv_data) uint8 item_count = (*itr)->items.size(); // max count is MAX_MAIL_ITEMS (12) - size_t next_mail_size = 2+4+1+((*itr)->messageType == MAIL_NORMAL ? 8 : 4)+4*8+((*itr)->subject.size()+1)+1+item_count*(1+4+4+7*3*4+4+4+4+4+4+4+1); + size_t next_mail_size = 2+4+1+((*itr)->messageType == MAIL_NORMAL ? 8 : 4)+4*8+((*itr)->subject.size()+1)+((*itr)->body.size()+1)+1+item_count*(1+4+4+7*3*4+4+4+4+4+4+4+1); if (data.wpos()+next_mail_size > maxPacketSize) { @@ -573,14 +570,6 @@ void WorldSession::HandleGetMailList(WorldPacket & recv_data) continue; } - uint32 show_flags = 0; - if ((*itr)->messageType != MAIL_NORMAL) - show_flags |= MAIL_SHOW_DELETE; - if ((*itr)->messageType == MAIL_AUCTION) - show_flags |= MAIL_SHOW_AUCTION; - if ((*itr)->HasItems() && (*itr)->messageType == MAIL_NORMAL) - show_flags |= MAIL_SHOW_RETURN; - data << uint16(next_mail_size); // Message size data << uint32((*itr)->messageID); // Message ID data << uint8((*itr)->messageType); // Message Type @@ -601,14 +590,14 @@ void WorldSession::HandleGetMailList(WorldPacket & recv_data) } data << uint32((*itr)->COD); // COD - data << uint32((*itr)->itemTextId); // sure about this - data << uint32(0); // unknown + data << uint32(0); // probably changed in 3.3.3 data << uint32((*itr)->stationery); // stationery (Stationery.dbc) data << uint32((*itr)->money); // Gold - data << uint32(show_flags); // unknown, 0x4 - auction, 0x10 - normal + data << uint32((*itr)->checked); // flags data << float(((*itr)->expire_time-time(NULL))/DAY); // Time data << uint32((*itr)->mailTemplateId); // mail template (MailTemplate.dbc) - data << (*itr)->subject; // Subject string - once 00, when mail type = 3 + data << (*itr)->subject; // Subject string - once 00, when mail type = 3, max 256 + data << (*itr)->body; // message? max 8000 data << uint8(item_count); // client limit is 0x10 for (uint8 i = 0; i < item_count; ++i) @@ -657,19 +646,23 @@ void WorldSession::HandleGetMailList(WorldPacket & recv_data) ///this function is called when client needs mail message body, or when player clicks on item which has ITEM_FIELD_ITEM_TEXT_ID > 0 void WorldSession::HandleItemTextQuery(WorldPacket & recv_data) { - uint32 itemTextId; - uint32 mailId; //this value can be item id in bag, but it is also mail id - uint32 unk; //maybe something like state - 0x70000000 - - recv_data >> itemTextId >> mailId >> unk; + uint64 itemGuid; + recv_data >> itemGuid; - //some check needed, if player has item with guid mailId, or has mail with id mailId + sLog.outDebug("CMSG_ITEM_TEXT_QUERY item guid: %u", GUID_LOPART(itemGuid)); - sLog.outDebug("CMSG_ITEM_TEXT_QUERY itemguid: %u, mailId: %u, unk: %u", itemTextId, mailId, unk); - - WorldPacket data(SMSG_ITEM_TEXT_QUERY_RESPONSE, (4+10));// guess size - data << itemTextId; - data << objmgr.GetItemText(itemTextId); + WorldPacket data(SMSG_ITEM_TEXT_QUERY_RESPONSE, (4+10)); // guess size + + if (Item *item = _player->GetItemByGuid(itemGuid)) + { + data << uint8(0); // has text + data << uint64(itemGuid); // item guid + data << objmgr.GetItemText(item->GetGUIDLow()); // max 8000 + } + else + { + data << uint8(1); // no text + } SendPacket(&data); } @@ -681,7 +674,6 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket & recv_data) recv_data >> mailbox; recv_data >> mailId; - recv_data.read_skip<uint32>(); // mailTemplateId, non need, Mail store own 100% correct value anyway if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; @@ -689,16 +681,21 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket & recv_data) Player *pl = _player; Mail* m = pl->GetMail(mailId); - if (!m || !m->itemTextId && !m->mailTemplateId || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) + if (!m || (m->body.empty() && !m->mailTemplateId) || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) { pl->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_ERR_INTERNAL_ERROR); return; } - uint32 itemTextId = m->itemTextId; + Item *bodyItem = new Item; // This is not bag and then can be used new Item. + if (!bodyItem->Create(objmgr.GenerateLowGuid(HIGHGUID_ITEM), MAIL_BODY_ITEM_TEMPLATE, pl)) + { + delete bodyItem; + return; + } - // in mail template case we need create new text id - if (!itemTextId) + // in mail template case we need create new item text + if(m->mailTemplateId) { MailTemplateEntry const* mailTemplateEntry = sMailTemplateStore.LookupEntry(m->mailTemplateId); if (!mailTemplateEntry) @@ -707,18 +704,13 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket & recv_data) return; } - itemTextId = objmgr.CreateItemText(mailTemplateEntry->content[GetSessionDbcLocale()]); + objmgr.CreateItemText(bodyItem->GetGUIDLow(), mailTemplateEntry->content[GetSessionDbcLocale()]); } + else + objmgr.CreateItemText(bodyItem->GetGUIDLow(), m->body); - Item *bodyItem = new Item; // This is not bag and then can be used new Item. - if (!bodyItem->Create(objmgr.GenerateLowGuid(HIGHGUID_ITEM), MAIL_BODY_ITEM_TEMPLATE, pl)) - { - delete bodyItem; - return; - } - - //bodyItem->SetUInt32Value(ITEM_FIELD_ITEM_TEXT_ID , itemTextId); - bodyItem->SetUInt32Value(ITEM_FIELD_CREATOR, m->sender); + bodyItem->SetUInt32Value(ITEM_FIELD_CREATOR, m->sender); + bodyItem->SetFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPER | ITEM_FLAGS_REFUNDABLE_2 | ITEM_FLAGS_UNK1); sLog.outDetail("HandleMailCreateTextItem mailid=%u",mailId); @@ -726,12 +718,11 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket & recv_data) uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, bodyItem, false); if (msg == EQUIP_ERR_OK) { - m->itemTextId = 0; + m->checked = m->checked | MAIL_CHECK_MASK_COPIED; m->state = MAIL_STATE_CHANGED; pl->m_mailsUpdated = true; pl->StoreItem(dest, bodyItem, true); - //bodyItem->SetState(ITEM_NEW, pl); is set automatically pl->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_OK); } else @@ -966,12 +957,16 @@ void MailDraft::SendMailTo(MailReceiver const& receiver, MailSender const& sende // Add to DB std::string safe_subject = GetSubject(); - CharacterDatabase.BeginTransaction(); CharacterDatabase.escape_string(safe_subject); - CharacterDatabase.PExecute("INSERT INTO mail (id,messageType,stationery,mailTemplateId,sender,receiver,subject,itemTextId,has_items,expire_time,deliver_time,money,cod,checked) " - "VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%s', '%u', '%u', '" UI64FMTD "','" UI64FMTD "', '%u', '%u', '%d')", - mailId, sender.GetMailMessageType(), sender.GetStationery(), GetMailTemplateId(), sender.GetSenderId(), receiver.GetPlayerGUIDLow(), safe_subject.c_str(), GetBodyId(), (m_items.empty() ? 0 : 1), (uint64)expire_time, (uint64)deliver_time, m_money, m_COD, checked); + + std::string safe_body = GetBody(); + CharacterDatabase.BeginTransaction(); + CharacterDatabase.escape_string(safe_body); + + CharacterDatabase.PExecute("INSERT INTO mail (id,messageType,stationery,mailTemplateId,sender,receiver,subject,body,has_items,expire_time,deliver_time,money,cod,checked) " + "VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%s', '%s', '%u', '" UI64FMTD "','" UI64FMTD "', '%u', '%u', '%d')", + mailId, sender.GetMailMessageType(), sender.GetStationery(), GetMailTemplateId(), sender.GetSenderId(), receiver.GetPlayerGUIDLow(), safe_subject.c_str(), safe_body.c_str(),(m_items.empty() ? 0 : 1), (uint64)expire_time, (uint64)deliver_time, m_money, m_COD, checked); for (MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter) { @@ -991,7 +986,7 @@ void MailDraft::SendMailTo(MailReceiver const& receiver, MailSender const& sende m->messageID = mailId; m->mailTemplateId = GetMailTemplateId(); m->subject = GetSubject(); - m->itemTextId = GetBodyId(); + m->body = GetBody(); m->money = GetMoney(); m->COD = GetCOD(); diff --git a/src/game/Mail.h b/src/game/Mail.h index 3832f34c07a..7a28787fec5 100644 --- a/src/game/Mail.h +++ b/src/game/Mail.h @@ -44,16 +44,17 @@ enum MailCheckMask { MAIL_CHECK_MASK_NONE = 0x00, MAIL_CHECK_MASK_READ = 0x01, - MAIL_CHECK_MASK_AUCTION = 0x04, + MAIL_CHECK_MASK_RETURNED = 0x02, /// This mail was returned. + MAIL_CHECK_MASK_COPIED = 0x04, /// This mail was copied. MAIL_CHECK_MASK_COD_PAYMENT = 0x08, - MAIL_CHECK_MASK_RETURNED = 0x10 + MAIL_CHECK_MASK_HAS_BODY = 0x10, /// This mail has body text. }; // gathered from Stationery.dbc enum MailStationery { - MAIL_STATIONERY_UNKNOWN = 1, - MAIL_STATIONERY_NORMAL = 41, + MAIL_STATIONERY_TEST = 1, + MAIL_STATIONERY_DEFAULT = 41, MAIL_STATIONERY_GM = 61, MAIL_STATIONERY_AUCTION = 62, MAIL_STATIONERY_VAL = 64, @@ -81,11 +82,11 @@ enum MailAuctionAnswers class MailSender { public: // Constructors - MailSender(MailMessageType messageType, uint32 sender_guidlow_or_entry, MailStationery stationery = MAIL_STATIONERY_NORMAL) + MailSender(MailMessageType messageType, uint32 sender_guidlow_or_entry, MailStationery stationery = MAIL_STATIONERY_DEFAULT) : m_messageType(messageType), m_senderId(sender_guidlow_or_entry), m_stationery(stationery) { } - MailSender(Object* sender, MailStationery stationery = MAIL_STATIONERY_NORMAL); + MailSender(Object* sender, MailStationery stationery = MAIL_STATIONERY_DEFAULT); MailSender(AuctionEntry* sender); public: // Accessors MailMessageType GetMailMessageType() const { return m_messageType; } @@ -117,16 +118,16 @@ class MailDraft public: // Constructors explicit MailDraft(uint16 mailTemplateId, bool need_items = true) - : m_mailTemplateId(mailTemplateId), m_mailTemplateItemsNeed(need_items), m_bodyId(0), m_money(0), m_COD(0) + : m_mailTemplateId(mailTemplateId), m_mailTemplateItemsNeed(need_items), m_money(0), m_COD(0) {} - MailDraft(std::string subject, uint32 itemTextId = 0) - : m_mailTemplateId(0), m_mailTemplateItemsNeed(false), m_subject(subject), m_bodyId(itemTextId), m_money(0), m_COD(0) {} + MailDraft(std::string subject, std::string body) + : m_mailTemplateId(0), m_mailTemplateItemsNeed(false), m_subject(subject), m_body(body), m_money(0), m_COD(0) {} public: // Accessors uint16 GetMailTemplateId() const { return m_mailTemplateId; } std::string const& GetSubject() const { return m_subject; } - uint32 GetBodyId() const { return m_bodyId; } uint32 GetMoney() const { return m_money; } uint32 GetCOD() const { return m_COD; } + std::string const& GetBody() const { return m_body; } public: // modifiers MailDraft& AddItem(Item* item); MailDraft& AddMoney(uint32 money) { m_money = money; return *this; } @@ -141,7 +142,7 @@ class MailDraft uint16 m_mailTemplateId; bool m_mailTemplateItemsNeed; std::string m_subject; - uint32 m_bodyId; + std::string m_body; MailItemMap m_items; // Keep the items in a map to avoid duplicate guids (which can happen), store only low part of guid @@ -164,7 +165,7 @@ struct Mail uint32 sender; uint32 receiver; std::string subject; - uint32 itemTextId; + std::string body; std::vector<MailItemInfo> items; std::vector<uint32> removedItems; time_t expire_time; diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 337bf0074f3..5864da2e914 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -713,6 +713,10 @@ void WorldSession::HandleBugOpcode(WorldPacket & recv_data) void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data) { sLog.outDetail("WORLD: Received CMSG_RECLAIM_CORPSE"); + + uint64 guid; + recv_data >> guid; + if (GetPlayer()->isAlive()) return; @@ -736,9 +740,6 @@ void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data) if (!corpse->IsWithinDistInMap(GetPlayer(), CORPSE_RECLAIM_RADIUS, true)) return; - uint64 guid; - recv_data >> guid; - // resurrect GetPlayer()->ResurrectPlayer(GetPlayer()->InBattleGround() ? 1.0f : 0.5f); @@ -750,14 +751,14 @@ void WorldSession::HandleResurrectResponseOpcode(WorldPacket & recv_data) { sLog.outDetail("WORLD: Received CMSG_RESURRECT_RESPONSE"); - if (GetPlayer()->isAlive()) - return; - uint64 guid; uint8 status; recv_data >> guid; recv_data >> status; + if (GetPlayer()->isAlive()) + return; + if (status == 0) { GetPlayer()->clearResurrectRequestData(); // reject diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index 6019d545717..f6380016af0 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -273,22 +273,24 @@ void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket & recv_data) _player->ModifyMoney(-int32(nSpellCost)); WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer - data << uint64(guid) << uint32(0xB3); + data << uint64(guid); + data << uint32(0xB3); // index from SpellVisualKit.dbc SendPacket(&data); data.Initialize(SMSG_PLAY_SPELL_IMPACT, 12); // visual effect on player - data << uint64(_player->GetGUID()) << uint32(0x016A); + data << uint64(_player->GetGUID()); + data << uint32(0x016A); // index from SpellVisualKit.dbc SendPacket(&data); // learn explicitly or cast explicitly if (trainer_spell->IsCastable()) - //FIXME: prof. spell entry in trainer list not marked gray until list re-open. _player->CastSpell(_player,trainer_spell->spell,true); else - _player->learnSpell(spellId,false); + _player->learnSpell(spellId, false); data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12); - data << uint64(guid) << uint32(trainer_spell->spell); + data << uint64(guid); + data << uint32(spellId); // should be same as in packet from client SendPacket(&data); } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 38555a2cb44..daf97dfa2f7 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -5087,9 +5087,9 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp) sLog.outDebug("Returning mails current time: hour: %d, minute: %d, second: %d ", localtime(&basetime)->tm_hour, localtime(&basetime)->tm_min, localtime(&basetime)->tm_sec); //delete all old mails without item and without body immediately, if starting server if (!serverUp) - CharacterDatabase.PExecute("DELETE FROM mail WHERE expire_time < '" UI64FMTD "' AND has_items = '0' AND itemTextId = 0", (uint64)basetime); + CharacterDatabase.PExecute("DELETE FROM mail WHERE expire_time < '" UI64FMTD "' AND has_items = '0' AND body = ''", (uint64)basetime); // 0 1 2 3 4 5 6 7 8 9 - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT id,messageType,sender,receiver,itemTextId,has_items,expire_time,cod,checked,mailTemplateId FROM mail WHERE expire_time < '" UI64FMTD "'", (uint64)basetime); + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT id,messageType,sender,receiver,has_items,expire_time,cod,checked,mailTemplateId FROM mail WHERE expire_time < '" UI64FMTD "'", (uint64)basetime); if (!result) { barGoLink bar(1); @@ -5118,13 +5118,12 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp) m->messageType = fields[1].GetUInt8(); m->sender = fields[2].GetUInt32(); m->receiver = fields[3].GetUInt32(); - m->itemTextId = fields[4].GetUInt32(); - bool has_items = fields[5].GetBool(); - m->expire_time = (time_t)fields[6].GetUInt64(); + bool has_items = fields[4].GetBool(); + m->expire_time = (time_t)fields[5].GetUInt64(); m->deliver_time = 0; - m->COD = fields[7].GetUInt32(); - m->checked = fields[8].GetUInt32(); - m->mailTemplateId = fields[9].GetInt16(); + m->COD = fields[6].GetUInt32(); + m->checked = fields[7].GetUInt32(); + m->mailTemplateId = fields[8].GetInt16(); Player *pl = 0; if (serverUp) @@ -5153,7 +5152,7 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp) while (resultItems->NextRow()); } //if it is mail from AH, it shouldn't be returned, but deleted - if (m->messageType != MAIL_NORMAL || (m->checked & (MAIL_CHECK_MASK_AUCTION | MAIL_CHECK_MASK_COD_PAYMENT | MAIL_CHECK_MASK_RETURNED))) + if (m->messageType != MAIL_NORMAL || m->messageType == MAIL_AUCTION || (m->checked & (MAIL_CHECK_MASK_COD_PAYMENT | MAIL_CHECK_MASK_RETURNED))) { // mail open and then not returned for (std::vector<MailItemInfo>::iterator itr2 = m->items.begin(); itr2 != m->items.end(); ++itr2) @@ -5168,9 +5167,6 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp) } } - if (m->itemTextId) - CharacterDatabase.PExecute("DELETE FROM item_text WHERE id = '%u'", m->itemTextId); - //deletemail = true; //delmails << m->messageID << ", "; CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", m->messageID); @@ -6061,28 +6057,17 @@ uint32 ObjectMgr::GenerateMailID() return m_mailid++; } -uint32 ObjectMgr::GenerateItemTextID() -{ - if (m_ItemTextId >= 0xFFFFFFFE) - { - sLog.outError("Item text ids overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - return m_ItemTextId++; -} - -uint32 ObjectMgr::CreateItemText(std::string text) +void ObjectMgr::CreateItemText(uint32 guid, std::string text) { - uint32 newItemTextId = GenerateItemTextID(); - //insert new itempage to container - mItemTexts[ newItemTextId ] = text; - //save new itempage + // insert new item text to container + mItemTexts[ guid ] = text; + + // save new item text CharacterDatabase.escape_string(text); - //any Delete query needed, itemTextId is maximum of all ids + std::ostringstream query; - query << "INSERT INTO item_text (id,text) VALUES ('" << newItemTextId << "', '" << text << "')"; + query << "INSERT INTO item_text (id,text) VALUES ( '" << guid << "', '" << text << "')"; CharacterDatabase.Execute(query.str().c_str()); //needs to be run this way, because mail body may be more than 1024 characters - return newItemTextId; } uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 5447fe23d51..e5391ed74ef 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -715,12 +715,12 @@ class ObjectMgr uint32 GenerateAuctionID(); uint64 GenerateEquipmentSetGuid(); uint32 GenerateGuildId(); - uint32 GenerateItemTextID(); + //uint32 GenerateItemTextID(); uint32 GenerateMailID(); uint32 GeneratePetNumber(); - uint32 CreateItemText(std::string text); - void AddItemText(uint32 itemTextId, std::string text) { mItemTexts[itemTextId] = text; } + void CreateItemText(uint32 guid, std::string text); + void AddItemText(uint32 guid, std::string text) { mItemTexts[guid] = text; } std::string GetItemText(uint32 id) { ItemTextMap::const_iterator itr = mItemTexts.find(id); diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index 99817661b91..b0241d60204 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -1341,7 +1341,9 @@ enum Opcodes SMSG_UNKNOWN_1302 = 0x516, // something with player movement (move event 58?) CMSG_UNKNOWN_1303 = 0x517, // something with player movement (move event 58?) SMSG_UNKNOWN_1304 = 0x518, // something with player movement (move event 58?), speed packet - NUM_MSG_TYPES = 0x519 + UMSG_UNKNOWN_1305 = 0x519, // not found + UMSG_UNKNOWN_1306 = 0x51A, // not found + NUM_MSG_TYPES = 0x51B }; /// Player state diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp index 2c80f7468f3..000a8d16b41 100644 --- a/src/game/PetitionsHandler.cpp +++ b/src/game/PetitionsHandler.cpp @@ -399,12 +399,12 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data) { if (objmgr.GetGuildByName(newname)) { - SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_EXISTS); + SendGuildCommandResult(GUILD_CREATE_S, newname, ERR_GUILD_NAME_EXISTS_S); return; } if (objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname)) { - SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID); + SendGuildCommandResult(GUILD_CREATE_S, newname, ERR_GUILD_NAME_INVALID); return; } } @@ -509,7 +509,7 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) } if (_player->GetGuildIdInvited()) { - SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD); + SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_INVITED_TO_GUILD_S); return; } } @@ -543,8 +543,8 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4)); data << uint64(petitionguid); - data << uint64(_player->GetGUID()) - data << (uint32)PETITION_SIGN_OK; + data << uint64(_player->GetGUID()); + data << uint32(PETITION_SIGN_OK); // close at signer side SendPacket(&data); @@ -625,7 +625,7 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data) if (player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { // player is too low level to join an arena team - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ARENA_TEAM_PLAYER_TO_LOW); + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ARENA_TEAM_TARGET_TOO_LOW_S); return; } @@ -656,7 +656,7 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data) if (player->GetGuildIdInvited()) { - SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD); + SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_INVITED_TO_GUILD_S); return; } } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 115df736b3d..51d40ff812e 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -3209,7 +3209,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen if (!IsInWorld() || disabled) // at spells loading, no output, but allow save addSpell(prev_spell,active,true,true,disabled); else // at normal learning - learnSpell(prev_spell,true); + learnSpell(prev_spell, true); } PlayerSpell *newspell = new PlayerSpell; @@ -3325,7 +3325,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen if (skill_max_value < new_skill_max_value) skill_max_value = new_skill_max_value; - SetSkill(spellLearnSkill->skill,skill_value,skill_max_value); + SetSkill(spellLearnSkill->skill, spellLearnSkill->step, skill_value, skill_max_value); } else { @@ -3346,13 +3346,13 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen switch(GetSkillRangeType(pSkill,_spell_idx->second->racemask != 0)) { case SKILL_RANGE_LANGUAGE: - SetSkill(pSkill->id, 300, 300); + SetSkill(pSkill->id, GetSkillStep(pSkill->id), 300, 300); break; case SKILL_RANGE_LEVEL: - SetSkill(pSkill->id, 1, GetMaxSkillValueForLevel()); + SetSkill(pSkill->id, GetSkillStep(pSkill->id), 1, GetMaxSkillValueForLevel()); break; case SKILL_RANGE_MONO: - SetSkill(pSkill->id, 1, 1); + SetSkill(pSkill->id, GetSkillStep(pSkill->id), 1, 1); break; default: break; @@ -3371,7 +3371,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen if (!IsInWorld() || !itr2->second.active) // at spells loading, no output, but allow save addSpell(itr2->second.spell,itr2->second.active,true,true,false); else // at normal learning - learnSpell(itr2->second.spell,true); + learnSpell(itr2->second.spell, true); } } @@ -3445,7 +3445,7 @@ void Player::learnSpell(uint32 spell_id, bool dependent) { PlayerSpellMap::iterator iter = m_spells.find(node->next); if (iter != m_spells.end() && iter->second->disabled) - learnSpell(node->next,false); + learnSpell(node->next, false); } } @@ -3453,8 +3453,9 @@ void Player::learnSpell(uint32 spell_id, bool dependent) if (!learning || !IsInWorld()) return; - WorldPacket data(SMSG_LEARNED_SPELL, 4); + WorldPacket data(SMSG_LEARNED_SPELL, 6); data << uint32(spell_id); + data << uint16(0); GetSession()->SendPacket(&data); } @@ -3534,7 +3535,7 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank) { uint32 prev_spell = spellmgr.GetPrevSpellInChain(spell_id); if (!prev_spell) // first rank, remove skill - SetSkill(spellLearnSkill->skill,0,0); + SetSkill(spellLearnSkill->skill, 0, 0, 0); else { // search prev. skill setting by spell ranks chain @@ -3546,7 +3547,7 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank) } if (!prevSkill) // not found prev skill setting, remove skill - SetSkill(spellLearnSkill->skill,0,0); + SetSkill(spellLearnSkill->skill, 0, 0, 0); else // set to prev. skill setting values { uint32 skill_value = GetPureSkillValue(prevSkill->skill); @@ -3560,7 +3561,7 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank) if (skill_max_value > new_skill_max_value) skill_max_value = new_skill_max_value; - SetSkill(prevSkill->skill,skill_value,skill_max_value); + SetSkill(prevSkill->skill, prevSkill->step, skill_value, skill_max_value); } } @@ -3586,7 +3587,7 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank) (IsProfessionSkill(pSkill->id) || _spell_idx->second->racemask != 0)) continue; - SetSkill(pSkill->id, 0, 0); + SetSkill(pSkill->id, GetSkillStep(pSkill->id), 0, 0); } } } @@ -3609,7 +3610,7 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank) { // I cannot see why mangos has these lines. //if (learn_low_rank) - // learnSpell(prev_id,false); + // learnSpell(prev_id, false); } // if ranked non-stackable spell: need activate lesser rank and update dendence state else if (cur_active && !SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0) @@ -4224,7 +4225,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC RemovePetitionsAndSigns(playerguid, 10); // return back all mails with COD and Item 0 1 2 3 4 5 6 7 - QueryResult_AutoPtr resultMail = CharacterDatabase.PQuery("SELECT id,messageType,mailTemplateId,sender,subject,itemTextId,money,has_items FROM mail WHERE receiver='%u' AND has_items<>0 AND cod<>0", guid); + QueryResult_AutoPtr resultMail = CharacterDatabase.PQuery("SELECT id,messageType,mailTemplateId,sender,subject,body,money,has_items FROM mail WHERE receiver='%u' AND has_items<>0 AND cod<>0", guid); if (resultMail) { do @@ -4236,7 +4237,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC uint16 mailTemplateId= fields[2].GetUInt16(); uint32 sender = fields[3].GetUInt32(); std::string subject = fields[4].GetCppString(); - uint32 itemTextId = fields[5].GetUInt32(); + std::string body = fields[5].GetCppString(); uint32 money = fields[6].GetUInt32(); bool has_items = fields[7].GetBool(); @@ -4252,7 +4253,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC continue; } - MailDraft draft(subject, itemTextId); + MailDraft draft(subject, body); if (mailTemplateId) draft = MailDraft(mailTemplateId,false); // itesm already included @@ -5434,7 +5435,7 @@ bool Player::UpdateCraftSkill(uint32 spellid) if (spellEntry && spellEntry->Mechanic == MECHANIC_DISCOVERY) { if (uint32 discoveredSpell = GetSkillDiscoverySpell(_spell_idx->second->skillId, spellid, this)) - learnSpell(discoveredSpell,false); + learnSpell(discoveredSpell, false); } uint32 craft_skill_gain = sWorld.getConfig(CONFIG_SKILL_GAIN_CRAFTING); @@ -5717,7 +5718,7 @@ void Player::UpdateSkillsToMaxSkillsForLevel() // This functions sets a skill line value (and adds if doesn't exist yet) // To "remove" a skill line, set it's values to zero -void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal) +void Player::SetSkill(uint16 id, uint16 step, uint16 currVal, uint16 maxVal) { if (!id) return; @@ -5729,6 +5730,9 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal) { if (currVal) { + // update step + SetUInt32Value(PLAYER_SKILL_INDEX(itr->second.pos), MAKE_PAIR32(id, step)); + // update value SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos),MAKE_SKILL_VALUE(currVal,maxVal)); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; @@ -5767,14 +5771,11 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal) sLog.outError("Skill not found in SkillLineStore: skill #%u", id); return; } - // enable unlearn button for primary professions only - if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION) - SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,1)); - else - SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,0)); - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(currVal,maxVal)); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL,id); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL,id); + + SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id, step)); + SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(currVal, maxVal)); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id); // insert new entry or update if not deleted old entry yet if (itr != mSkillStatus.end()) @@ -5816,6 +5817,18 @@ bool Player::HasSkill(uint32 skill) const return (itr != mSkillStatus.end() && itr->second.uState != SKILL_DELETED); } +uint16 Player::GetSkillStep(uint16 skill) const +{ + if (!skill) + return 0; + + SkillStatusMap::const_iterator itr = mSkillStatus.find(skill); + if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) + return 0; + + return PAIR32_HIPART(GetUInt32Value(PLAYER_SKILL_INDEX(itr->second.pos))); +} + uint16 Player::GetSkillValue(uint32 skill) const { if (!skill) @@ -13519,11 +13532,11 @@ void Player::PrepareQuestMenu(uint64 guid) uint32 quest_id = i->second; QuestStatus status = GetQuestStatus(quest_id); if (status == QUEST_STATUS_COMPLETE && !GetQuestRewardStatus(quest_id)) - qm.AddMenuItem(quest_id, DIALOG_STATUS_UNK2); + qm.AddMenuItem(quest_id, 4); else if (status == QUEST_STATUS_INCOMPLETE) - qm.AddMenuItem(quest_id, DIALOG_STATUS_UNK2); + qm.AddMenuItem(quest_id, 4); //else if (status == QUEST_STATUS_AVAILABLE) - // qm.AddMenuItem(quest_id, DIALOG_STATUS_CHAT); + // qm.AddMenuItem(quest_id, 2); } for (QuestRelations::const_iterator i = pObjectQR->lower_bound(pObject->GetEntry()); i != pObjectQR->upper_bound(pObject->GetEntry()); ++i) @@ -13535,9 +13548,9 @@ void Player::PrepareQuestMenu(uint64 guid) QuestStatus status = GetQuestStatus(quest_id); if (pQuest->IsAutoComplete() && CanTakeQuest(pQuest, false)) - qm.AddMenuItem(quest_id, DIALOG_STATUS_UNK2); + qm.AddMenuItem(quest_id, 4); else if (status == QUEST_STATUS_NONE && CanTakeQuest(pQuest, false)) - qm.AddMenuItem(quest_id, DIALOG_STATUS_CHAT); + qm.AddMenuItem(quest_id, 2); } } @@ -13549,7 +13562,7 @@ void Player::SendPreparedQuest(uint64 guid) QuestMenuItem const& qmi0 = questMenu.GetItem(0); - uint32 status = qmi0.m_qIcon; + uint32 icon = qmi0.m_qIcon; // single element case if (questMenu.MenuItemCount() == 1) @@ -13560,9 +13573,9 @@ void Player::SendPreparedQuest(uint64 guid) if (pQuest) { - if (status == DIALOG_STATUS_UNK2 && !GetQuestRewardStatus(quest_id)) + if (icon == 4 && !GetQuestRewardStatus(quest_id)) PlayerTalkClass->SendQuestGiverRequestItems(pQuest, guid, CanRewardQuest(pQuest, false), true); - else if (status == DIALOG_STATUS_UNK2) + else if (icon == 4) PlayerTalkClass->SendQuestGiverRequestItems(pQuest, guid, CanRewardQuest(pQuest, false), true); // Send completable on repeatable and autoCompletable quest if player don't have quest // TODO: verify if check for !pQuest->IsDaily() is really correct (possibly not) @@ -14106,7 +14119,7 @@ void Player::RewardQuest(Quest const *pQuest, uint32 reward, Object* questGiver, // Send reward mail if (uint32 mail_template_id = pQuest->GetRewMailTemplateId()) - MailDraft(mail_template_id).SendMailTo(this, questGiver, MAIL_CHECK_MASK_NONE, pQuest->GetRewMailDelaySecs()); + MailDraft(mail_template_id).SendMailTo(MailReceiver(this), MailSender(questGiver), MAIL_CHECK_MASK_HAS_BODY, pQuest->GetRewMailDelaySecs()); if (pQuest->IsDaily()) { @@ -16532,7 +16545,7 @@ void Player::_LoadInventory(QueryResult_AutoPtr result, uint32 timediff) std::string subject = GetSession()->GetTrinityString(LANG_NOT_EQUIPPED_ITEM); // fill mail - MailDraft draft(subject); + MailDraft draft(subject, "There's were problems with equipping item(s)."); for (uint8 i = 0; !problematicItems.empty() && i < MAX_MAIL_ITEMS; ++i) { @@ -16613,7 +16626,7 @@ void Player::_LoadMail() { m_mail.clear(); //mails are in right order 0 1 2 3 4 5 6 7 8 9 10 11 12 13 - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT id,messageType,sender,receiver,subject,itemTextId,has_items,expire_time,deliver_time,money,cod,checked,stationery,mailTemplateId FROM mail WHERE receiver = '%u' ORDER BY id DESC",GetGUIDLow()); + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT id,messageType,sender,receiver,subject,body,has_items,expire_time,deliver_time,money,cod,checked,stationery,mailTemplateId FROM mail WHERE receiver = '%u' ORDER BY id DESC",GetGUIDLow()); if (result) { do @@ -16625,11 +16638,11 @@ void Player::_LoadMail() m->sender = fields[2].GetUInt32(); m->receiver = fields[3].GetUInt32(); m->subject = fields[4].GetCppString(); - m->itemTextId = fields[5].GetUInt32(); + m->body = fields[5].GetCppString(); bool has_items = fields[6].GetBool(); - m->expire_time = (time_t)fields[7].GetUInt64(); + m->expire_time = (time_t)fields[7].GetUInt64(); m->deliver_time = (time_t)fields[8].GetUInt64(); - m->money = fields[9].GetUInt32(); + m->money = fields[9].GetUInt32(); m->COD = fields[10].GetUInt32(); m->checked = fields[11].GetUInt32(); m->stationery = fields[12].GetUInt8(); @@ -17643,7 +17656,7 @@ void Player::_SaveMail() if (m->state == MAIL_STATE_CHANGED) { CharacterDatabase.PExecute("UPDATE mail SET itemTextId = '%u',has_items = '%u',expire_time = '" UI64FMTD "', deliver_time = '" UI64FMTD "',money = '%u',cod = '%u',checked = '%u' WHERE id = '%u'", - m->itemTextId, m->HasItems() ? 1 : 0, (uint64)m->expire_time, (uint64)m->deliver_time, m->money, m->COD, m->checked, m->messageID); + m->HasItems() ? 1 : 0, (uint64)m->expire_time, (uint64)m->deliver_time, m->money, m->COD, m->checked, m->messageID); if (m->removedItems.size()) { for (std::vector<uint32>::iterator itr2 = m->removedItems.begin(); itr2 != m->removedItems.end(); ++itr2) @@ -17657,8 +17670,6 @@ void Player::_SaveMail() if (m->HasItems()) for (std::vector<MailItemInfo>::iterator itr2 = m->items.begin(); itr2 != m->items.end(); ++itr2) CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", itr2->item_guid); - if (m->itemTextId) - CharacterDatabase.PExecute("DELETE FROM item_text WHERE id = '%u'", m->itemTextId); CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", m->messageID); CharacterDatabase.PExecute("DELETE FROM mail_items WHERE mail_id = '%u'", m->messageID); } @@ -20677,7 +20688,7 @@ void Player::learnDefaultSpells() if (!IsInWorld()) // will send in INITIAL_SPELLS in list anyway at map add addSpell(tspell,true,true,true,false); else // but send in normal spell in game learn case - learnSpell(tspell,true); + learnSpell(tspell, true); } } @@ -20804,7 +20815,7 @@ void Player::learnSkillRewardedSpells(uint32 skill_id, uint32 skill_value) else if (!IsInWorld()) addSpell(pAbility->spellId,true,true,true,false); else - learnSpell(pAbility->spellId,true); + learnSpell(pAbility->spellId, true); } } } @@ -21096,7 +21107,7 @@ void Player::AutoUnequipOffhandIfNeed(bool force /*= false*/) CharacterDatabase.CommitTransaction(); std::string subject = GetSession()->GetTrinityString(LANG_NOT_EQUIPPED_ITEM); - MailDraft(subject).AddItem(offItem).SendMailTo(this, MailSender(this, MAIL_STATIONERY_GM)); + MailDraft(subject, "There's were problems with equipping this item.").AddItem(offItem).SendMailTo(this, MailSender(this, MAIL_STATIONERY_GM)); } } @@ -22198,7 +22209,7 @@ bool Player::IsKnowHowFlyIn(uint32 mapid, uint32 zone) const void Player::learnSpellHighRank(uint32 spellid) { - learnSpell(spellid,false); + learnSpell(spellid, false); if (uint32 next = spellmgr.GetNextSpellInChain(spellid)) learnSpellHighRank(next); @@ -22287,21 +22298,21 @@ void Player::_LoadSkills(QueryResult_AutoPtr result) base_skill = 1; // skill mast be known and then > 0 in any case if (GetPureSkillValue(SKILL_FIRST_AID) < base_skill) - SetSkill(SKILL_FIRST_AID,base_skill, base_skill); + SetSkill(SKILL_FIRST_AID, 0, base_skill, base_skill); if (GetPureSkillValue(SKILL_AXES) < base_skill) - SetSkill(SKILL_AXES, base_skill,base_skill); + SetSkill(SKILL_AXES, 0, base_skill, base_skill); if (GetPureSkillValue(SKILL_DEFENSE) < base_skill) - SetSkill(SKILL_DEFENSE, base_skill,base_skill); + SetSkill(SKILL_DEFENSE, 0, base_skill, base_skill); if (GetPureSkillValue(SKILL_POLEARMS) < base_skill) - SetSkill(SKILL_POLEARMS, base_skill,base_skill); + SetSkill(SKILL_POLEARMS, 0, base_skill, base_skill); if (GetPureSkillValue(SKILL_SWORDS) < base_skill) - SetSkill(SKILL_SWORDS, base_skill,base_skill); + SetSkill(SKILL_SWORDS, 0, base_skill, base_skill); if (GetPureSkillValue(SKILL_2H_AXES) < base_skill) - SetSkill(SKILL_2H_AXES, base_skill,base_skill); + SetSkill(SKILL_2H_AXES, 0, base_skill, base_skill); if (GetPureSkillValue(SKILL_2H_SWORDS) < base_skill) - SetSkill(SKILL_2H_SWORDS, base_skill,base_skill); + SetSkill(SKILL_2H_SWORDS, 0, base_skill, base_skill); if (GetPureSkillValue(SKILL_UNARMED) < base_skill) - SetSkill(SKILL_UNARMED, base_skill,base_skill); + SetSkill(SKILL_UNARMED, 0, base_skill, base_skill); } } diff --git a/src/game/Player.h b/src/game/Player.h index 93574049bad..d9d0797cfe4 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1874,7 +1874,7 @@ class Player : public Unit, public GridObject<Player> void UpdateWeaponSkill (WeaponAttackType attType); void UpdateCombatSkills(Unit *pVictim, WeaponAttackType attType, bool defence); - void SetSkill(uint32 id, uint16 currVal, uint16 maxVal); + void SetSkill(uint16 id, uint16 step, uint16 currVal, uint16 maxVal); uint16 GetMaxSkillValue(uint32 skill) const; // max + perm. bonus + temp bonus uint16 GetPureMaxSkillValue(uint32 skill) const; // max uint16 GetSkillValue(uint32 skill) const; // skill value + perm. bonus + temp bonus @@ -1882,6 +1882,7 @@ class Player : public Unit, public GridObject<Player> uint16 GetPureSkillValue(uint32 skill) const; // skill value int16 GetSkillPermBonusValue(uint32 skill) const; int16 GetSkillTempBonusValue(uint32 skill) const; + uint16 GetSkillStep(uint16 skill) const; // 0...6 bool HasSkill(uint32 skill) const; void learnSkillRewardedSpells(uint32 id, uint32 value); diff --git a/src/game/QuestDef.h b/src/game/QuestDef.h index a6f1592fe03..c72b823a124 100644 --- a/src/game/QuestDef.h +++ b/src/game/QuestDef.h @@ -108,9 +108,9 @@ enum __QuestGiverStatus { DIALOG_STATUS_NONE = 0, DIALOG_STATUS_UNAVAILABLE = 1, - DIALOG_STATUS_CHAT = 2, // 3.1 - may be changed - DIALOG_STATUS_UNK1 = 3, // 3.1 - DIALOG_STATUS_UNK2 = 4, // 3.1 + DIALOG_STATUS_LOW_LEVEL_AVAILABLE = 2, + DIALOG_STATUS_LOW_LEVEL_REWARD_REP = 3, + DIALOG_STATUS_LOW_LEVEL_AVAILABLE_REP = 4, DIALOG_STATUS_INCOMPLETE = 5, DIALOG_STATUS_REWARD_REP = 6, DIALOG_STATUS_AVAILABLE_REP = 7, @@ -239,7 +239,7 @@ class Quest bool IsRepeatable() const { return QuestFlags & QUEST_TRINITY_FLAGS_REPEATABLE; } bool IsAutoComplete() const { return QuestMethod ? false : true; } uint32 GetFlags() const { return QuestFlags; } - bool IsDaily() const { return QuestFlags & (QUEST_FLAGS_DAILY; } + bool IsDaily() const { return QuestFlags & QUEST_FLAGS_DAILY; } bool IsWeekly() const { return QuestFlags & QUEST_FLAGS_WEEKLY; } bool IsAutoAccept() const { return QuestFlags & QUEST_FLAGS_AUTO_ACCEPT; } diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp index f479aa79874..53bb4335169 100644 --- a/src/game/QuestHandler.cpp +++ b/src/game/QuestHandler.cpp @@ -625,7 +625,7 @@ uint32 WorldSession::getDialogStatus(Player *pPlayer, Object* questgiver, uint32 result2 = DIALOG_STATUS_AVAILABLE; } else - result2 = DIALOG_STATUS_CHAT; + result2 = DIALOG_STATUS_LOW_LEVEL_AVAILABLE; } else result2 = DIALOG_STATUS_UNAVAILABLE; diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index f41948411ea..16d4e90a5fb 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -764,7 +764,9 @@ enum SpellEffects SPELL_EFFECT_160 = 160, SPELL_EFFECT_TALENT_SPEC_COUNT = 161, SPELL_EFFECT_TALENT_SPEC_SELECT = 162, - TOTAL_SPELL_EFFECTS = 163 + SPELL_EFFECT_163 = 163, + SPELL_EFFECT_164 = 164, + TOTAL_SPELL_EFFECTS = 165 }; enum SpellCastResult @@ -2657,24 +2659,25 @@ enum ResponseCodes CHAR_LOGIN_NO_CHARACTER = 0x53, CHAR_LOGIN_LOCKED_FOR_TRANSFER = 0x54, CHAR_LOGIN_LOCKED_BY_BILLING = 0x55, - - CHAR_NAME_SUCCESS = 0x56, - CHAR_NAME_FAILURE = 0x57, - CHAR_NAME_NO_NAME = 0x58, - CHAR_NAME_TOO_SHORT = 0x59, - CHAR_NAME_TOO_LONG = 0x5A, - CHAR_NAME_INVALID_CHARACTER = 0x5B, - CHAR_NAME_MIXED_LANGUAGES = 0x5C, - CHAR_NAME_PROFANE = 0x5D, - CHAR_NAME_RESERVED = 0x5E, - CHAR_NAME_INVALID_APOSTROPHE = 0x5F, - CHAR_NAME_MULTIPLE_APOSTROPHES = 0x60, - CHAR_NAME_THREE_CONSECUTIVE = 0x61, - CHAR_NAME_INVALID_SPACE = 0x62, - CHAR_NAME_CONSECUTIVE_SPACES = 0x63, - CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x64, - CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x65, - CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x66 + CHAR_LOGIN_LOCKED_BY_MOBILE_AH = 0x56, + + CHAR_NAME_SUCCESS = 0x57, + CHAR_NAME_FAILURE = 0x58, + CHAR_NAME_NO_NAME = 0x59, + CHAR_NAME_TOO_SHORT = 0x5A, + CHAR_NAME_TOO_LONG = 0x5B, + CHAR_NAME_INVALID_CHARACTER = 0x5C, + CHAR_NAME_MIXED_LANGUAGES = 0x5D, + CHAR_NAME_PROFANE = 0x5E, + CHAR_NAME_RESERVED = 0x5F, + CHAR_NAME_INVALID_APOSTROPHE = 0x60, + CHAR_NAME_MULTIPLE_APOSTROPHES = 0x61, + CHAR_NAME_THREE_CONSECUTIVE = 0x62, + CHAR_NAME_INVALID_SPACE = 0x63, + CHAR_NAME_CONSECUTIVE_SPACES = 0x64, + CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x65, + CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x66, + CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x67 }; /// Ban function modes diff --git a/src/game/SkillHandler.cpp b/src/game/SkillHandler.cpp index 24e1fb045b1..312065f9f13 100644 --- a/src/game/SkillHandler.cpp +++ b/src/game/SkillHandler.cpp @@ -90,6 +90,6 @@ void WorldSession::HandleUnlearnSkillOpcode(WorldPacket & recv_data) { uint32 skill_id; recv_data >> skill_id; - GetPlayer()->SetSkill(skill_id, 0, 0); + GetPlayer()->SetSkill(skill_id, 0, 0, 0); } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 9e9c3e2f16d..c71402d41d2 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -438,7 +438,7 @@ Spell::Spell(Unit* Caster, SpellEntry const *info, bool triggered, uint64 origin } for (int i=0; i <3; ++i) - m_currentBasePoints[i] = m_spellValue->EffectBasePoints[i]; + m_currentBasePoints[i] = m_spellInfo->CalculateSimpleValue(i); m_spellState = SPELL_STATE_NULL; @@ -6752,7 +6752,7 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk { // skill bonus provided by casting spell (mostly item spells) // add the damage modifier from the spell casted (cheat lock / skeleton key etc.) (use m_currentBasePoints, CalculateDamage returns wrong value) - uint32 spellSkillBonus = uint32(m_currentBasePoints[effIndex]+1); + uint32 spellSkillBonus = uint32(m_currentBasePoints[effIndex]); reqSkillValue = lockInfo->Skill[j]; // castitem check: rogue using skeleton keys. the skill values should not be added in this case. @@ -6781,15 +6781,15 @@ void Spell::SetSpellValue(SpellValueMod mod, int32 value) switch(mod) { case SPELLVALUE_BASE_POINT0: - m_spellValue->EffectBasePoints[0] = value - int32(m_spellInfo->EffectBaseDice[0]); + m_spellValue->EffectBasePoints[0] = value - int32(1); m_currentBasePoints[0] = m_spellValue->EffectBasePoints[0]; //this should be removed in the future break; case SPELLVALUE_BASE_POINT1: - m_spellValue->EffectBasePoints[1] = value - int32(m_spellInfo->EffectBaseDice[1]); + m_spellValue->EffectBasePoints[1] = value - int32(1); m_currentBasePoints[1] = m_spellValue->EffectBasePoints[1]; break; case SPELLVALUE_BASE_POINT2: - m_spellValue->EffectBasePoints[2] = value - int32(m_spellInfo->EffectBaseDice[2]); + m_spellValue->EffectBasePoints[2] = value - int32(1); m_currentBasePoints[2] = m_spellValue->EffectBasePoints[2]; break; case SPELLVALUE_RADIUS_MOD: diff --git a/src/game/SpellAuraEffects.cpp b/src/game/SpellAuraEffects.cpp index 4cdc09492fa..b632f79718a 100644 --- a/src/game/SpellAuraEffects.cpp +++ b/src/game/SpellAuraEffects.cpp @@ -376,7 +376,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= AuraEffect::AuraEffect(Aura * base, uint8 effIndex, int32 *baseAmount, Unit * caster) : m_base(base), m_spellProto(base->GetSpellProto()), m_spellmod(NULL), m_periodicTimer(0), m_tickNumber(0), m_effIndex(effIndex), m_isPeriodic(false), m_canBeRecalculated(true), - m_baseAmount (baseAmount ? *baseAmount : m_spellProto->EffectBasePoints[m_effIndex]) + m_baseAmount (baseAmount ? *baseAmount : m_spellProto->EffectBasePoints[m_effIndex] + 1) { CalculatePeriodic(caster, true); @@ -409,7 +409,7 @@ int32 AuraEffect::CalculateAmount(Unit * caster) if (caster) amount = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_baseAmount, NULL); else - amount = m_baseAmount + m_spellProto->EffectBaseDice[m_effIndex]; + amount = m_baseAmount + 1; // check item enchant aura cast if (!amount && caster) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 37d80381fa9..067edf5a7d4 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -228,6 +228,8 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectNULL, //160 SPELL_EFFECT_160 unused &Spell::EffectSpecCount, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert) &Spell::EffectActivateSpec, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec + &Spell::EffectNULL, //163 + &Spell::EffectNULL, //164 cancel's some aura... }; void Spell::EffectNULL(uint32 /*i*/) @@ -3765,7 +3767,7 @@ void Spell::EffectLearnSpell(uint32 i) Player *player = (Player*)unitTarget; uint32 spellToLearn = (m_spellInfo->Id == 483 || m_spellInfo->Id == 55884) ? damage : m_spellInfo->EffectTriggerSpell[i]; - player->learnSpell(spellToLearn,false); + player->learnSpell(spellToLearn, false); sLog.outDebug("Spell: Player %u has learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow()); } @@ -3980,7 +3982,7 @@ void Spell::EffectLearnSkill(uint32 i) uint32 skillid = m_spellInfo->EffectMiscValue[i]; uint16 skillval = unitTarget->ToPlayer()->GetPureSkillValue(skillid); - unitTarget->ToPlayer()->SetSkill(skillid, skillval?skillval:1, damage*75); + unitTarget->ToPlayer()->SetSkill(skillid, m_spellInfo->CalculateSimpleValue(i), skillval?skillval:1, damage*75); } void Spell::EffectAddHonor(uint32 /*i*/) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index d318467a7fe..6dbc4ac96e7 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1823,11 +1823,12 @@ void SpellMgr::LoadSpellLearnSkills() { SpellLearnSkillNode dbc_node; dbc_node.skill = entry->EffectMiscValue[i]; + dbc_node.step = entry->CalculateSimpleValue(i); if (dbc_node.skill != SKILL_RIDING) dbc_node.value = 1; else - dbc_node.value = entry->CalculateSimpleValue(i)*75; - dbc_node.maxvalue = entry->CalculateSimpleValue(i)*75; + dbc_node.value = dbc_node.step * 75; + dbc_node.maxvalue = dbc_node.step * 75; SpellLearnSkillNode const* db_node = GetSpellLearnSkill(spell); diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 70f114057f0..8c576bb93bf 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -790,9 +790,10 @@ typedef std::pair<SpellsRequiringSpellMap::const_iterator,SpellsRequiringSpellMa // Spell learning properties (accessed using SpellMgr functions) struct SpellLearnSkillNode { - uint32 skill; - uint32 value; // 0 - max skill value for player level - uint32 maxvalue; // 0 - max skill value for player level + uint16 skill; + uint16 step; + uint16 value; // 0 - max skill value for player level + uint16 maxvalue; // 0 - max skill value for player level }; typedef std::map<uint32, SpellLearnSkillNode> SpellLearnSkillMap; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 4b57fcbb76e..043dc8cc179 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -12240,17 +12240,22 @@ int32 Unit::CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_inde level -= int32(spellProto->spellLevel); float basePointsPerLevel = spellProto->EffectRealPointsPerLevel[effect_index]; - float randomPointsPerLevel = 1; int32 basePoints = int32(effBasePoints + level * basePointsPerLevel); - int32 randomPoints = int32(spellProto->EffectDieSides[effect_index] + level * randomPointsPerLevel); + int32 randomPoints = int32(spellProto->EffectDieSides[effect_index]); - // range can have possitive and negative values, so order its for irand - int32 randvalue = int32(1) >= randomPoints - ? irand(randomPoints, int32(1)) - : irand(int32(1), randomPoints); + int32 value = basePoints; + + if (randomPoints != 0) + { + // range can have positive and negative values, so order its for irand + int32 randvalue = (0 > randomPoints) + ? irand(randomPoints, 0) + : irand(0, randomPoints); - int32 value = basePoints + randvalue; - //random damage + basePoints += randvalue; + } + + // random damage //if (comboDamage != 0 && unitPlayer /*&& target && (target->GetGUID() == unitPlayer->GetComboTarget())*/) if (m_movedPlayer) if (uint8 comboPoints = m_movedPlayer->GetComboPoints()) diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp index 7189c42a803..c9e22ba85dd 100644 --- a/src/game/WorldSocket.cpp +++ b/src/game/WorldSocket.cpp @@ -259,10 +259,14 @@ int WorldSocket::open (void *a) WorldPacket packet (SMSG_AUTH_CHALLENGE, 24); packet << uint32(1); // 1...31 packet << m_Seed; - packet << uint32(0xF3539DA3); // random data - packet << uint32(0x6E8547B9); // random data - packet << uint32(0x9A6AA2F8); // random data - packet << uint32(0xA4F170F4); // random data + + BigNumber seed1; + seed1.SetRand(16 * 8); + packet.append(seed1.AsByteArray(16), 16); // new encryption seeds + + BigNumber seed2; + seed2.SetRand(16 * 8); + packet.append(seed2.AsByteArray(16), 16); // new encryption seeds if (SendPacket (packet) == -1) return -1; diff --git a/src/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp b/src/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp index dcc4b4dc3ec..56b012dc79c 100644 --- a/src/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp +++ b/src/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp @@ -341,7 +341,7 @@ struct boss_headless_horsemanAI : public ScriptedAI { confl->EffectApplyAuraName[0] = SPELL_AURA_PERIODIC_DAMAGE_PERCENT; confl->EffectBasePoints[0] = 10; - confl->EffectBaseDice[0] = 10; + //confl->EffectBaseDice[0] = 10; confl->DmgMultiplier[0] = 1; } /* |