Exemple #1
0
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;
}
Exemple #2
0
// 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;
}