Beispiel #1
0
void LootMgr::LoadLootTables(const char* szTableName, LootStore* LootTable)
{

	vector< pair< uint32, vector< tempy > > > db_cache;
	vector< pair< uint32, vector< tempy > > >::iterator itr;
	db_cache.reserve(10000);
	LootStore::iterator tab;
	QueryResult* result = WorldDatabase.Query("SELECT * FROM %s ORDER BY entryid ASC", szTableName);
	if(!result)
	{
		sLog.Error("LootMgr", "Loading loot from table %s failed.", szTableName);
		return;
	}
	uint32 entry_id = 0;
	uint32 last_entry = 0;

	uint32 total = (uint32) result->GetRowCount();
	int pos = 0;
	vector< tempy > ttab;
	tempy t;
	do
	{
		Field* fields = result->Fetch();
		entry_id = fields[ 0 ].GetUInt32();
		if(entry_id < last_entry)
		{
			sLog.Error("LootMgr", "WARNING: Out of order loot table being loaded.");
			return;
		}
		if(entry_id != last_entry)
		{
			if(last_entry != 0)
				db_cache.push_back(make_pair(last_entry, ttab));
			ttab.clear();
		}

		t.itemid = fields[ 1 ].GetUInt32();
		t.chance = fields[ 2 ].GetFloat();
		t.chance_2 = fields[ 3 ].GetFloat();

		t.chance3 = fields[ 4 ].GetFloat();
		t.chance4 = fields[ 5 ].GetFloat();

		t.mincount = fields[ 6 ].GetUInt32();
		t.maxcount = fields[ 7 ].GetUInt32();

		ttab.push_back(t);

		last_entry = entry_id;
	}
	while(result->NextRow());

	//last list was not pushed in
	if(last_entry != 0 && ttab.size())
		db_cache.push_back(make_pair(last_entry, ttab));

	pos = 0;
	total = (uint32)db_cache.size();
	ItemPrototype* proto;
	uint32 itemid;

	for(itr = db_cache.begin(); itr != db_cache.end(); ++itr)
	{
		entry_id = (*itr).first;
		if(LootTable->end() == LootTable->find(entry_id))
		{
			StoreLootList list;

			list.count = static_cast< uint32 >(itr->second.size());
			list.items = new StoreLootItem[list.count];

			uint32 ind = 0;

			for(vector< tempy >::iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2)
			{
				//Omit items that are not in db to prevent future bugs
				itemid = itr2->itemid;
				proto = ItemPrototypeStorage.LookupEntry(itemid);
				if(!proto)
				{
					list.items[ind].item.itemproto = NULL;
					Log.Error("LootMgr", "Loot for %u contains non-existant item %u . (%s)", entry_id, itemid, szTableName);
				}
				else
				{
					list.items[ind].item.itemproto = proto;
					list.items[ind].item.displayid = proto->DisplayInfoID;
					list.items[ind].chance = itr2->chance;
					list.items[ind].chance2 = itr2->chance_2;
					list.items[ind].chance3 = itr2->chance3;
					list.items[ind].chance4 = itr2->chance4;
					list.items[ind].mincount = itr2->mincount;
					list.items[ind].maxcount = itr2->maxcount;

					if( proto->HasFlag( ITEM_FLAG_FREE_FOR_ALL ) )
						list.items[ ind ].ffa_loot = 1;
					else
						list.items[ ind ].ffa_loot = 0;

					if(LootTable == &GOLoot)
					{
						if(proto->Class == ITEM_CLASS_QUEST)
						{
							sQuestMgr.SetGameObjectLootQuest(itr->first, itemid);
							quest_loot_go[entry_id].insert(proto->ItemId);
						}
					}
				}
				ind++;
			}
			(*LootTable)[entry_id] = list;
		}
	}

	//sLog.outString("  %d loot templates loaded from %s", db_cache.size(), szTableName);
	delete result;
}
Beispiel #2
0
void LootMgr::AddLoot(Loot* loot, uint32 itemid, uint32 mincount, uint32 maxcount)
{
	uint32 i;
	uint32 count;
	ItemPrototype* itemproto = ItemPrototypeStorage.LookupEntry(itemid);

	if(itemproto)  // this check is needed until loot DB is fixed
	{
		if(mincount == maxcount)
			count = maxcount;
		else
			count = RandomUInt(maxcount - mincount) + mincount;

		for(i = 0; i < loot->items.size(); ++i)
		{
			//itemid rand match a already placed item, if item is stackable and unique(stack), increment it, otherwise skips
			if((loot->items[i].item.itemproto == itemproto) && itemproto->MaxCount && ((loot->items[i].iItemsCount + count) < itemproto->MaxCount))
			{
				if(itemproto->Unique && ((loot->items[i].iItemsCount + count) < itemproto->Unique))
				{
					loot->items[i].iItemsCount += count;
					break;
				}
				else if(!itemproto->Unique)
				{
					loot->items[i].iItemsCount += count;
					break;
				}
			}
		}

		if(i != loot->items.size())
			return;

		_LootItem item;
		item.itemproto = itemproto;
		item.displayid = itemproto->DisplayInfoID;

		__LootItem itm;
		itm.item = item;
		itm.iItemsCount = count;
		itm.roll = NULL;
		itm.passed = false;

		if( itemproto->HasFlag( ITEM_FLAG_FREE_FOR_ALL ) )
			itm.ffa_loot = 1;
		else
			itm.ffa_loot = 0;

		itm.has_looted.clear();

		if(itemproto->Quality > 1 && itemproto->ContainerSlots == 0)
		{
			itm.iRandomProperty = GetRandomProperties(itemproto);
			itm.iRandomSuffix = GetRandomSuffix(itemproto);
		}
		else
		{
			// save some calls :P
			itm.iRandomProperty = NULL;
			itm.iRandomSuffix = NULL;
		}

		loot->items.push_back(itm);
	}
	if(loot->items.size() > 16)
	{
		std::vector<__LootItem>::iterator item_to_remove;
		std::vector<__LootItem>::iterator itr;
		uint32 item_quality;
		bool quest_item;
		while(loot->items.size() > 16)
		{
			item_to_remove = loot->items.begin();
			item_quality = 0;
			quest_item = false;
			for(itr = loot->items.begin(); itr != loot->items.end(); ++itr)
			{
				item_quality = (*itr).item.itemproto->Quality;
				quest_item = (*itr).item.itemproto->Class == ITEM_CLASS_QUEST;
				if((*item_to_remove).item.itemproto->Quality > item_quality && !quest_item)
				{
					item_to_remove = itr;
				}
			}
			loot->items.erase(item_to_remove);
		}
	}
}
Beispiel #3
0
void WorldSession::HandleUseItemOpcode(WorldPacket & recvPacket)
{
	CHECK_INWORLD_RETURN

	typedef std::list<Aura*> AuraList;

	Player* p_User = GetPlayer();
	LOG_DETAIL("WORLD: got use Item packet, data length = %i", recvPacket.size());
	int8 tmp1, slot;
	uint8 unk; //Alice : added in 3.0.2
	uint64 item_guid;
	uint8 cn;
	uint32 spellId = 0;
	uint32 glyphIndex;
	bool found = false;

	recvPacket >> tmp1;
	recvPacket >> slot;
	recvPacket >> cn;
	recvPacket >> spellId;
	recvPacket >> item_guid;
	recvPacket >> glyphIndex;
	recvPacket >> unk;

	Item* tmpItem = NULL;
	tmpItem = p_User->GetItemInterface()->GetInventoryItem(tmp1, slot);
	if(!tmpItem)
		tmpItem = p_User->GetItemInterface()->GetInventoryItem(slot);
	if(!tmpItem)
		return;
	ItemPrototype* itemProto = tmpItem->GetProto();

	// only some consumable items can be used in arenas
	if( ( itemProto->Class == ITEM_CLASS_CONSUMABLE ) &&
		!itemProto->HasFlag( ITEM_FLAG_USEABLE_IN_ARENA ) &&
		( GetPlayer()->m_bg != NULL ) &&
		IS_ARENA( GetPlayer()->m_bg->GetType() ) )
	{
		GetPlayer()->GetItemInterface()->BuildInventoryChangeError(tmpItem, NULL, INV_ERR_NOT_DURING_ARENA_MATCH);
		return;
	}

	if(tmpItem->IsSoulbound())     // SouldBind item will be used after SouldBind()
	{
		if(sScriptMgr.CallScriptedItem(tmpItem, _player))
			return;
	}

	if(_player->getDeathState() == CORPSE)
		return;

	if(itemProto->Bonding == ITEM_BIND_ON_USE)
		tmpItem->SoulBind();

	if(sScriptMgr.CallScriptedItem(tmpItem, _player))
		return;

	if(itemProto->InventoryType != 0 && !_player->GetItemInterface()->IsEquipped(itemProto->ItemId))  //Equipable items cannot be used before they're equipped. Prevents exploits
		return;//Prevents exploits such as keeping an on-use trinket in your bag and using WPE to use it from your bag in mid-combat.

	if(itemProto->QuestId)
	{
		// Item Starter
		Quest* qst = QuestStorage.LookupEntry(itemProto->QuestId);
		if(!qst)
			return;

		WorldPacket data;
		sQuestMgr.BuildQuestDetails(&data, qst, tmpItem, 0, language, _player);
		SendPacket(&data);
	}

	// Let's check if the item even has that spell
	for(int i = 0; i < 5; ++i)
	{
		if(itemProto->Spells[i].Trigger == USE && itemProto->Spells[i].Id == spellId)
		{
			found = true;
			break;//found 1 already
		}
	}

	// Let's see if it is an onuse spellid
	if(tmpItem->HasOnUseSpellID(spellId))
		found = true;

	// We didn't find the spell, so the player is probably trying to cheat
	// with an edited itemcache.wdb
	//
	// Altough this could also happen after a DB update
	// if he/she didn't delete his/her cache.
	if(found == false)
	{

		this->Disconnect();
		Anticheat_Log->writefromsession(this, "Player tried to use an item with a spell that didn't match the spell in the database.");
		Anticheat_Log->writefromsession(this, "Possibly corrupted or intentionally altered itemcache.wdb");
		Anticheat_Log->writefromsession(this, "Itemid: %lu", itemProto->ItemId);
		Anticheat_Log->writefromsession(this, "Spellid: %lu", spellId);
		Anticheat_Log->writefromsession(this, "Player was disconnected");

		return;
	}

	SpellCastTargets targets(recvPacket, _player->GetGUID());

	SpellEntry* spellInfo = dbcSpell.LookupEntryForced(spellId);
	if(spellInfo == NULL)
	{
		LOG_DETAIL("ERROR: WORLD: unknown spell id %i", spellId);
		return;
	}

	if(spellInfo->AuraInterruptFlags & AURA_INTERRUPT_ON_STAND_UP)
	{
		if(p_User->CombatStatus.IsInCombat() || p_User->IsMounted())
		{
			_player->GetItemInterface()->BuildInventoryChangeError(tmpItem, NULL, INV_ERR_CANT_DO_IN_COMBAT);
			return;
		}

		if(p_User->GetStandState() != 1)
			p_User->SetStandState(STANDSTATE_SIT);
		// loop through the auras and removing existing eating spells
	}
	else   // cebernic: why not stand up
	{
		if(!p_User->CombatStatus.IsInCombat() && !p_User->IsMounted())
		{
			if(p_User->GetStandState())
			{
				p_User->SetStandState(STANDSTATE_STAND);
			}
		}
	}

	// cebernic: remove stealth on using item
	if(!(spellInfo->AuraInterruptFlags & ATTRIBUTESEX_NOT_BREAK_STEALTH))
	{
		if(p_User->IsStealth())
			p_User->RemoveAllAuraType(SPELL_AURA_MOD_STEALTH);
	}

	if(itemProto->RequiredLevel)
	{
		if(_player->getLevel() < itemProto->RequiredLevel)
		{
			_player->GetItemInterface()->BuildInventoryChangeError(tmpItem, NULL, INV_ERR_ITEM_RANK_NOT_ENOUGH);
			return;
		}
	}

	if(itemProto->RequiredSkill)
	{
		if(!_player->_HasSkillLine(itemProto->RequiredSkill))
		{
			_player->GetItemInterface()->BuildInventoryChangeError(tmpItem, NULL, INV_ERR_ITEM_RANK_NOT_ENOUGH);
			return;
		}

		if(itemProto->RequiredSkillRank)
		{
			if(_player->_GetSkillLineCurrent(itemProto->RequiredSkill, false) < itemProto->RequiredSkillRank)
			{
				_player->GetItemInterface()->BuildInventoryChangeError(tmpItem, NULL, INV_ERR_ITEM_RANK_NOT_ENOUGH);
				return;
			}
		}
	}

	if((itemProto->AllowableClass && !(_player->getClassMask() & itemProto->AllowableClass)) || (itemProto->AllowableRace && !(_player->getRaceMask() & itemProto->AllowableRace)))
	{
		_player->GetItemInterface()->BuildInventoryChangeError(tmpItem, NULL, INV_ERR_YOU_CAN_NEVER_USE_THAT_ITEM);
		return;
	}

	if(!_player->Cooldown_CanCast(spellInfo))
	{
		_player->SendCastResult(spellInfo->Id, SPELL_FAILED_NOT_READY, cn, 0);
		return;
	}


	if(_player->m_currentSpell)
	{
		_player->SendCastResult(spellInfo->Id, SPELL_FAILED_SPELL_IN_PROGRESS, cn, 0);
		return;
	}

	if(itemProto->ForcedPetId >= 0)
	{
		if(itemProto->ForcedPetId == 0)
		{
			if(_player->GetGUID() != targets.m_unitTarget)
			{
				_player->SendCastResult(spellInfo->Id, SPELL_FAILED_BAD_TARGETS, cn, 0);
				return;
			}
		}
		else
		{

			if(!_player->GetSummon() || _player->GetSummon()->GetEntry() != (uint32)itemProto->ForcedPetId)
			{
				_player->SendCastResult(spellInfo->Id, SPELL_FAILED_SPELL_IN_PROGRESS, cn, 0);
				return;
			}
		}
	}

	Spell* spell = sSpellFactoryMgr.NewSpell(_player, spellInfo, false, NULL);
	spell->extra_cast_number = cn;
	spell->i_caster = tmpItem;
	spell->m_glyphslot = glyphIndex;

	//GetPlayer()->setCurrentSpell(spell);
	spell->prepare(&targets);

#ifdef ENABLE_ACHIEVEMENTS
	_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM, itemProto->ItemId, 0, 0);
#endif

}