bool Player::SolveResearchProject(uint32 spellId, SpellCastTargets& targets) { uint16 skill_now = GetSkillValue(SKILL_ARCHAEOLOGY); if (!skill_now) return false; ResearchProjectEntry const* entry = NULL; for (std::set<ResearchProjectEntry const*>::const_iterator itr = sResearchProjectSet.begin(); itr != sResearchProjectSet.end(); ++itr) { if ((*itr)->spellId != spellId) continue; entry = (*itr); break; } if (!entry || !HasResearchProject(entry->ID)) return false; ResearchBranchEntry const* branch = NULL; for (uint32 i = 0; i < sResearchBranchStore.GetNumRows(); ++i) { ResearchBranchEntry const* _branch = sResearchBranchStore.LookupEntry(i); if (!_branch) continue; if (_branch->ID != entry->branchId) continue; branch = _branch; break; } if (!branch) return false; uint32 currencyId = branch->currency; int32 currencyAmt = int32(entry->req_currency_amt); ArchaeologyWeights weights = targets.GetWeights(); for (ArchaeologyWeights::iterator itr = weights.begin(); itr != weights.end(); ++itr) { ArchaeologyWeight& w = *itr; if (w.type == WEIGHT_KEYSTONE) { ItemPrototype const* proto = sObjectMgr.GetItemPrototype(w.keystone.itemId); if (!proto) return false; if (proto->GetCurrencySubstitutionId() != currencyId) return false; if (w.keystone.itemCount > entry->Complexity) return false; if (!HasItemCount(w.keystone.itemId, w.keystone.itemCount)) return false; currencyAmt -= int32(proto->CurrencySubstitutionCount * w.keystone.itemCount); } } if (currencyAmt > 0 && !HasCurrencyCount(currencyId, currencyAmt)) return false; ModifyCurrencyCount(currencyId, -currencyAmt); for (ArchaeologyWeights::iterator itr = weights.begin(); itr != weights.end(); ++itr) { ArchaeologyWeight& w = *itr; if (w.type == WEIGHT_KEYSTONE) DestroyItemCount(w.keystone.itemId, w.keystone.itemCount, true); } UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS, entry->ID, 1); AddCompletedProject(entry); ResearchProjectSet tempProjects; ResearchProjectSet tempRareProjects; float rare_chance = GetRareArtifactChance(skill_now); for (std::set<ResearchProjectEntry const*>::const_iterator itr = sResearchProjectSet.begin(); itr != sResearchProjectSet.end(); ++itr) { ResearchProjectEntry const* project = *itr; if (project->branchId != entry->branchId) continue; if (project->rare) { if (IsCompletedProject(project->ID, true)) continue; tempRareProjects.insert(project->ID); } else tempProjects.insert(project->ID); } ResearchProjectSet::const_iterator itr; if (tempRareProjects.size() > 0 && roll_chance_f(rare_chance)) { itr = tempRareProjects.begin(); std::advance(itr, urand(0, tempRareProjects.size() - 1)); } else { itr = tempProjects.begin(); std::advance(itr, urand(0, tempProjects.size() - 1)); } ReplaceResearchProject(entry->ID, *itr); _archaeologyChanged = true; WorldPacket data (SMSG_RESEARCH_COMPLETE, 4 * 3); data << uint32(entry->branchId); data << uint32(0); data << uint32(*itr); SendDirectMessage(&data); return true; }
// Return true is the bought item has a max count to force refresh of window by caller bool CPlayer::BuyItemFromMultiVendor(uint32 item, uint8 count, uint8 bag, uint8 slot) { DEBUG_LOG("WORLD: BuyItemFromMultiVendor"); // cheating attempt if (count < 1) count = 1; if (!isAlive()) return false; ItemPrototype const* pProto = ObjectMgr::GetItemPrototype(item); if (!pProto) { SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, item, 0); return false; } uint32 entry; ObjectGuid guid; GetMultiVendor(entry, guid); CreatureInfo const *cinfo = sObjectMgr.GetCreatureTemplate(entry); if (!cinfo) { BoxChat << MSG_COLOR_WHITE << "This vendor seems to be removed from the database. Please report that creature " << entry << " is missing." << std::endl; return false; } Creature* pCreature = GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); if (!pCreature) { DEBUG_LOG("WORLD: BuyItemFromMultiVendor - %s not found or you can't interact with him.", guid.GetString().c_str()); SendBuyError(BUY_ERR_DISTANCE_TOO_FAR, NULL, item, 0); return false; } VendorItemData const* vItems = sObjectMgr.GetNpcVendorItemList(entry); VendorItemData const* tItems = cinfo->VendorTemplateId ? sObjectMgr.GetNpcVendorTemplateItemList(cinfo->VendorTemplateId) : NULL; if ((!vItems || vItems->Empty()) && (!tItems || tItems->Empty())) { SendBuyError(BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0); return false; } uint32 vCount = vItems ? vItems->GetItemCount() : 0; uint32 tCount = tItems ? tItems->GetItemCount() : 0; size_t vendorslot = vItems ? vItems->FindItemSlot(item) : vCount; if (vendorslot >= vCount) vendorslot = vCount + (tItems ? tItems->FindItemSlot(item) : tCount); if (vendorslot >= vCount + tCount) { SendBuyError(BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0); return false; } VendorItem const* crItem = vendorslot < vCount ? vItems->GetItem(vendorslot) : tItems->GetItem(vendorslot - vCount); if (!crItem || crItem->item != item) // store diff item (cheating) { SendBuyError(BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0); return false; } uint32 totalCount = pProto->BuyCount * count; // check current item amount if it limited if (crItem->maxcount != 0) { if (pCreature->GetVendorItemCurrentCount(crItem) < totalCount) { SendBuyError(BUY_ERR_ITEM_ALREADY_SOLD, pCreature, item, 0); return false; } } if (uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank) { SendBuyError(BUY_ERR_REPUTATION_REQUIRE, pCreature, item, 0); return false; } if (uint32 extendedCostId = crItem->ExtendedCost) { ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(extendedCostId); if (!iece) { sLog.outError("Item %u have wrong ExtendedCost field value %u", pProto->ItemId, extendedCostId); return false; } // honor points price if (GetHonorPoints() < (iece->reqhonorpoints * count)) { SendEquipError(EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS, NULL, NULL); return false; } // arena points price if (GetArenaPoints() < (iece->reqarenapoints * count)) { SendEquipError(EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS, NULL, NULL); return false; } // item base price for (auto i = 0; i < MAX_EXTENDED_COST_ITEMS; ++i) { if (iece->reqitem[i] && !HasItemCount(iece->reqitem[i], iece->reqitemcount[i] * count)) { SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); return false; } } // check for personal arena rating requirement if (GetMaxPersonalArenaRatingRequirement() < iece->reqpersonalarenarating) { // probably not the proper equip err SendEquipError(EQUIP_ERR_CANT_EQUIP_RANK, NULL, NULL); return false; } } if (crItem->conditionId && !isGameMaster() && !sObjectMgr.IsPlayerMeetToCondition(crItem->conditionId, ToPlayer(), pCreature->GetMap(), pCreature, CONDITION_FROM_VENDOR)) { SendBuyError(BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0); return false; } uint32 price = pProto->BuyPrice * count; // reputation discount price = uint32(floor(price * GetReputationPriceDiscount(pCreature))); if (GetMoney() < price) { SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, item, 0); return false; } // if (GetAverageItemLevel() < crItem->itemlevel && !isGameMaster()) // { // // probably not the proper equip err // SendEquipError(EQUIP_ERR_CANT_EQUIP_RANK, NULL, NULL); // SendChatMessage("You need at least %u averange itemlevel.", crItem->itemlevel); // SendChatMessage("You currently have a averange itemlevel %u.", uint32(floor(GetAverageItemLevel()))); // return false; // } Item* pItem = NULL; if ((bag == NULL_BAG && slot == NULL_SLOT) || IsInventoryPos(bag, slot)) { ItemPosCountVec dest; InventoryResult msg = CanStoreNewItem(bag, slot, dest, item, totalCount); if (msg != EQUIP_ERR_OK) { SendEquipError(msg, NULL, NULL, item); return false; } ModifyMoney(-int32(price)); if (crItem->ExtendedCost) TakeExtendedCost(crItem->ExtendedCost, count); pItem = StoreNewItem(dest, item, true); } else if (IsEquipmentPos(bag, slot)) { if (totalCount != 1) { SendEquipError(EQUIP_ERR_ITEM_CANT_BE_EQUIPPED, NULL, NULL); return false; } uint16 dest; InventoryResult msg = CanEquipNewItem(slot, dest, item, false); if (msg != EQUIP_ERR_OK) { SendEquipError(msg, NULL, NULL, item); return false; } ModifyMoney(-int32(price)); if (crItem->ExtendedCost) TakeExtendedCost(crItem->ExtendedCost, count); pItem = EquipNewItem(dest, item, true); if (pItem) AutoUnequipOffhandIfNeed(); } else { SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL); return false; } if (!pItem) return false; uint32 new_count = pCreature->UpdateVendorItemCurrentCount(crItem, totalCount); WorldPacket data(SMSG_BUY_ITEM, 8 + 4 + 4 + 4); data << pCreature->GetObjectGuid(); data << uint32(vendorslot + 1); // numbered from 1 at client data << uint32(crItem->maxcount > 0 ? new_count : 0xFFFFFFFF); data << uint32(count); GetSession()->SendPacket(&data); SendNewItem(pItem, totalCount, true, false, false); return crItem->maxcount != 0; }