// 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()); }
// 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 }
// 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. }