Esempio n. 1
0
// Called by AddLootTableToNPC
// maxdrops = size of the array npcd
void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* itemlist, uint8 droplimit, uint8 mindrop) {
	const LootDrop_Struct* lds = GetLootDrop(lootdrop_id);
	if (!lds) {
		return;
	}

	if(lds->NumEntries == 0)
		return;

	if(droplimit == 0 && mindrop == 0) {
		for(uint32 i = 0; i < lds->NumEntries; ++i) {
			int charges = lds->Entries[i].multiplier;
			for(int j = 0; j < charges; ++j) {
				if(zone->random.Real(0.0, 100.0) <= lds->Entries[i].chance) {
					const EQEmu::ItemData* dbitem = GetItem(lds->Entries[i].item_id);
					npc->AddLootDrop(dbitem, itemlist, lds->Entries[i].item_charges, lds->Entries[i].minlevel,
									lds->Entries[i].maxlevel, lds->Entries[i].equip_item > 0 ? true : false, false);
				}
			}
		}
		return;
	}

	if(lds->NumEntries > 100 && droplimit == 0) {
		droplimit = 10;
	}

	if(droplimit < mindrop) {
		droplimit = mindrop;
	}

	float roll_t = 0.0f;
	float roll_t_min = 0.0f;
	bool active_item_list = false;
	for(uint32 i = 0; i < lds->NumEntries; ++i) {
		const EQEmu::ItemData* db_item = GetItem(lds->Entries[i].item_id);
		if(db_item) {
			roll_t += lds->Entries[i].chance;
			active_item_list = true;
		}
	}

	roll_t_min = roll_t;
	roll_t = EQEmu::ClampLower(roll_t, 100.0f);

	if(!active_item_list) {
		return;
	}

	for(int i = 0; i < mindrop; ++i) {
		float roll = (float)zone->random.Real(0.0, roll_t_min);
		for(uint32 j = 0; j < lds->NumEntries; ++j) {
			const EQEmu::ItemData* db_item = GetItem(lds->Entries[j].item_id);
			if(db_item) {
				if(roll < lds->Entries[j].chance) {
					npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel,
									 lds->Entries[j].maxlevel, lds->Entries[j].equip_item > 0 ? true : false, false);

					int charges = (int)lds->Entries[i].multiplier;
					charges = EQEmu::ClampLower(charges, 1);

					for(int k = 1; k < charges; ++k) {
						float c_roll = (float)zone->random.Real(0.0, 100.0);
						if(c_roll <= lds->Entries[i].chance) {
							npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel,
											 lds->Entries[j].maxlevel, lds->Entries[j].equip_item > 0 ? true : false, false);
						}
					}

					j = lds->NumEntries;
					break;
				}
				else {
					roll -= lds->Entries[j].chance;
				}
			}
		}
	}

	for(int i = mindrop; i < droplimit; ++i) {
		float roll = (float)zone->random.Real(0.0, roll_t);
		for(uint32 j = 0; j < lds->NumEntries; ++j) {
			const EQEmu::ItemData* db_item = GetItem(lds->Entries[j].item_id);
			if(db_item) {
				if(roll < lds->Entries[j].chance) {
					npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel,
										lds->Entries[j].maxlevel, lds->Entries[j].equip_item > 0 ? true : false, false);

					int charges = (int)lds->Entries[i].multiplier;
					charges = EQEmu::ClampLower(charges, 1);

					for(int k = 1; k < charges; ++k) {
						float c_roll = (float)zone->random.Real(0.0, 100.0);
						if(c_roll <= lds->Entries[i].chance) {
							npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel,
											lds->Entries[j].maxlevel, lds->Entries[j].equip_item > 0 ? true : false, false);
						}
					}

					j = lds->NumEntries;
					break;
				}
				else {
					roll -= lds->Entries[j].chance;
				}
			}
		}
	} // We either ran out of items or reached our limit.

	npc->UpdateEquipmentLight();
	// no wearchange associated with this function..so, this should not be needed
	//if (npc->UpdateActiveLightValue())
	//	npc->SendAppearancePacket(AT_Light, npc->GetActiveLightValue());
}
Esempio n. 2
0
// Called by AddLootTableToNPC
// maxdrops = size of the array npcd
void Database::AddLootDropToNPC(NPC* npc,int32 lootdrop_id, ItemList* itemlist) {
	const LootDrop_Struct* lds = GetLootDrop(lootdrop_id);
	if (!lds)
		return;

// This is Wiz's updated Pool Looting functionality.  Eventually, the database format should be moved over to use this
// or implemented to support both methods.  (A unique identifier in lootable_entries indicates to roll for a pool item
// in another table.
#ifdef POOLLOOTING
	printf("POOL!\n");
	int32 chancepool = 0;
	int32 items[50];
	int32 itemchance[50];
	int16 itemcharges[50];
	int8 i = 0;

	for (int m=0;m < 50;m++) {
		items[m]=0;
		itemchance[m]=0;
		itemcharges[m]=0;
	}

	for (int k=0; k<lds->NumEntries; k++) {
		items[i] = lds->Entries[k].item_id;
		itemchance[i] = lds->Entries[k].chance + chancepool;
		itemcharges[i] = lds->Entries[k].item_charges;
		chancepool += lds->Entries[k].chance;
		i++;
	}
	int32 res;
	i = 0;

    if (chancepool!=0) { //avoid divide by zero if some mobs have 0 for chancepool
        res = rand()%chancepool;
    }
    else {
        res = 0;
    }

	while (items[i] != 0) {
		if (res <= itemchance[i])
			break;
		else
			i++;
	}
	const Item_Struct* dbitem = database.GetItem(items[i]);
	if (dbitem == 0) {
		cerr << "Error in AddLootDropToNPC: dbitem=0, item#=" << items[i] << ", lootdrop_id=" << lootdrop_id << endl;
	}
	else {
		cout << "Adding item to Mob" << endl;
		ServerLootItem_Struct* item = new ServerLootItem_Struct;
		item->item_nr = dbitem->item_nr;
		item->charges = itemcharges[i];
		item->equipSlot = 0;
		(*itemlist).Append(item);
	}
#else
	int x=0;
	int32 k;
	int32 totalchance = 0;
	for (k=0; k<lds->NumEntries; k++) {
		totalchance += lds->Entries[k].chance;
	}
	int32 thischance = 0;
	for (k=0; k<lds->NumEntries; k++) {
		x++;
		LinkedListIterator<ServerLootItem_Struct*> iterator(*itemlist);
		iterator.Reset();
		int itemon=0;
		while(iterator.MoreElements()){
		const Item_Struct* item = database.GetItem(iterator.GetData()->item_nr);
		if(item)
			if(iterator.GetData()->item_nr==lds->Entries[k].item_id)
				itemon=1;
		iterator.Advance();
		}
		thischance += lds->Entries[k].chance;
		if (totalchance == 0 || (lds->Entries[k].chance != 0 && rand()%totalchance < thischance && (lds->Entries[k].chance!=100 && itemon==0)) || (lds->Entries[k].chance==100 && itemon==0)) {
			int32 itemid = lds->Entries[k].item_id;
			const Item_Struct* dbitem = database.GetItem(itemid);
			if (dbitem == 0) {
				cerr << "Error in AddLootDropToNPC: dbitem=0, item#=" << itemid << ", lootdrop_id=" << lootdrop_id << endl;
			}
			else {				
				ServerLootItem_Struct* item = new ServerLootItem_Struct;
				item->item_nr = dbitem->item_nr;
				item->charges = lds->Entries[k].item_charges;
				if (lds->Entries[k].equip_item==1){
					const Item_Struct* item2= database.GetItem(item->item_nr);
					char tmp[20];
					char newid[20];
					memset(newid, 0, sizeof(newid));
					for(int i=0;i<7;i++){
						if (!isalpha(item2->idfile[i])){
							strncpy(newid, &item2->idfile[i],5);
							i=8;
						}
					}
					//printf("Npc Name: %s, Item: %i\n",npc->GetName(),item2->item_nr);
					if (((item2->equipableSlots==24576) || (item2->equipableSlots==8192)) && (npc->d_meele_texture1==0)) {
						npc->d_meele_texture1=atoi(newid);
						npc->equipment[7]=item2->item_nr;
						if (item2->common.spellId0!=0)
							npc->CastToMob()->AddProcToWeapon(item2->common.spellId0,true);
						npc->AC+=item2->common.AC;
						npc->STR+=item2->common.STR;
						npc->INT+=item2->common.INT;
					}
					else if (((item2->equipableSlots==24576) || (item2->equipableSlots==16384)) && (npc->d_meele_texture2 ==0) && ((npc->GetLevel()>=13) || (item2->common.damage==0)))
					{
						if (item2->common.spellId0!=0)
							npc->CastToMob()->AddProcToWeapon(item2->common.spellId0,true);
						npc->equipment[8]=item2->item_nr;
						npc->d_meele_texture2=atoi(newid);
						npc->AC+=item2->common.AC;
						npc->STR+=item2->common.STR;
						npc->INT+=item2->common.INT;
					}
					else if ((item2->equipableSlots==4) && (npc->equipment[0]==0)){
						npc->equipment[0]=item2->item_nr;
						npc->AC+=item2->common.AC;
						npc->STR+=item2->common.STR;
						npc->INT+=item2->common.INT;
					}
					else if ((item2->equipableSlots==131072) && (npc->equipment[1]==0)){
						npc->equipment[1]=item2->common.material;
						npc->texture=item2->common.material;
						npc->AC+=item2->common.AC;
						npc->STR+=item2->common.STR;
						npc->INT+=item2->common.INT;
					}
					else if ((item2->equipableSlots==128) && (npc->equipment[2]==0)){
						npc->equipment[2]=item2->common.material;
						npc->AC+=item2->common.AC;
						npc->STR+=item2->common.STR;
						npc->INT+=item2->common.INT;
					}
					else if ((item2->equipableSlots==1536) && (npc->equipment[3]==0)){
						npc->equipment[3]=item2->common.material;
						npc->AC+=item2->common.AC;
						npc->STR+=item2->common.STR;
						npc->INT+=item2->common.INT;
					}
					else if ((item2->equipableSlots==4096) && (npc->equipment[4]==0)){
						npc->equipment[4]=item2->common.material;
						npc->AC+=item2->common.AC;
						npc->STR+=item2->common.STR;
						npc->INT+=item2->common.INT;
					}
					else if ((item2->equipableSlots==262144) && (npc->equipment[5]==0)){
						npc->equipment[5]=item2->common.material;
						npc->AC+=item2->common.AC;
						npc->STR+=item2->common.STR;
						npc->INT+=item2->common.INT;
					}
					else if ((item2->equipableSlots==524288) && (npc->equipment[6]==0)){
						npc->equipment[6]=item2->common.material;
						npc->AC+=item2->common.AC;
						npc->STR+=item2->common.STR;
						npc->INT+=item2->common.INT;
					}
					item->equipSlot = dbitem->equipableSlots;
				}
				(*itemlist).Append(item);
			}
			break;
		}
	}
#endif
}
Esempio n. 3
0
// Called by AddLootTableToNPC
// maxdrops = size of the array npcd
void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* itemlist, uint8 droplimit, uint8 mindrop) {
	const LootDrop_Struct* lds = GetLootDrop(lootdrop_id);
	if (!lds) {
		return;
	}
	if(lds->NumEntries == 0)	//nothing possible to add
		return;

	// Too long a list needs to be limited.
	if(lds->NumEntries > 99 && droplimit < 1)
		droplimit = lds->NumEntries/100;

	uint8 limit = 0;
	// Start at a random point in itemlist.
	uint32 item = MakeRandomInt(0, lds->NumEntries-1);
	// Main loop.
	for (uint32 i=0; i<lds->NumEntries;)
	{
		//Force the itemlist back to beginning.
		if (item > (lds->NumEntries-1))
			item = 0;

		uint8 charges = lds->Entries[item].multiplier;
		uint8 pickedcharges = 0;
		// Loop to check multipliers.
		for (uint32 x=1; x<=charges; x++)
		{
			// Actual roll.
			float thischance = 0.0;
			thischance = lds->Entries[item].chance;

			float drop_chance = 0.0;
			if(thischance != 100.0)
				drop_chance = MakeRandomFloat(0.0, 100.0);

#if EQDEBUG>=11
			LogFile->write(EQEMuLog::Debug, "Drop chance for npc: %s, this chance:%f, drop roll:%f", npc->GetName(), thischance, drop_chance);
#endif
			if (thischance == 100.0 || drop_chance < thischance)
			{
				uint32 itemid = lds->Entries[item].item_id;

				const Item_Struct* dbitem = GetItem(itemid);
				npc->AddLootDrop(dbitem, itemlist, lds->Entries[item].item_charges, lds->Entries[item].minlevel, lds->Entries[item].maxlevel, lds->Entries[item].equip_item, false);
				pickedcharges++;
			}
		}
		// Items with multipliers only count as 1 towards the limit.
		if(pickedcharges > 0)
			limit++;

		// If true, limit reached.
		if(limit >= droplimit && droplimit > 0)
			break;

		item++;
		i++;

		// We didn't reach our minimium, run loop again.
		if(i == lds->NumEntries){
			if(limit < mindrop){
				i = 0;
			}
		}
	} // We either ran out of items or reached our limit.
}