mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 05:21:29 +00:00
initial rewrite of loot code
This commit is contained in:
parent
b05dd45d62
commit
7fed01ddea
@ -23,13 +23,11 @@
|
||||
#include "masterentity.h"
|
||||
#include "zonedb.h"
|
||||
#include "../common/misc_functions.h"
|
||||
#ifdef _WINDOWS
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#include "../common/data_verification.h"
|
||||
|
||||
// Queries the loottable: adds item & coin to the npc
|
||||
void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* itemlist, uint32* copper, uint32* silver, uint32* gold, uint32* plat) {
|
||||
const LootTable_Struct* lts = 0;
|
||||
const LootTable_Struct* lts = nullptr;
|
||||
*copper = 0;
|
||||
*silver = 0;
|
||||
*gold = 0;
|
||||
@ -39,44 +37,37 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite
|
||||
if (!lts)
|
||||
return;
|
||||
|
||||
// do coin
|
||||
if (lts->mincash > lts->maxcash) {
|
||||
std::cerr << "Error in loottable #" << loottable_id << ": mincash > maxcash" << std::endl;
|
||||
uint32 min_cash = lts->mincash;
|
||||
uint32 max_cash = lts->maxcash;
|
||||
if(min_cash > max_cash) {
|
||||
uint32 t = min_cash;
|
||||
min_cash = max_cash;
|
||||
max_cash = t;
|
||||
}
|
||||
else if (lts->maxcash != 0) {
|
||||
|
||||
uint32 cash = 0;
|
||||
if (lts->mincash == lts->maxcash)
|
||||
cash = lts->mincash;
|
||||
else
|
||||
cash = MakeRandomInt(lts->mincash, lts->maxcash);
|
||||
if(max_cash > 0 && EQEmu::ValueWithin(lts->avgcoin, min_cash, max_cash)) {
|
||||
int avg_cash_roll = MakeRandomInt(1, 100);
|
||||
if(avg_cash_roll > 50) {
|
||||
cash = MakeRandomInt(lts->avgcoin, max_cash);
|
||||
} else {
|
||||
cash = MakeRandomInt(min_cash, lts->avgcoin);
|
||||
}
|
||||
} else {
|
||||
cash = MakeRandomInt(min_cash, max_cash);
|
||||
}
|
||||
|
||||
if(cash != 0) {
|
||||
if (lts->avgcoin != 0) {
|
||||
//this is some crazy ass stuff... and makes very little sense... dont use it, k?
|
||||
uint32 mincoin = (uint32) (lts->avgcoin * 0.75 + 1);
|
||||
uint32 maxcoin = (uint32) (lts->avgcoin * 1.25 + 1);
|
||||
*copper = MakeRandomInt(mincoin, maxcoin);
|
||||
*silver = MakeRandomInt(mincoin, maxcoin);
|
||||
*gold = MakeRandomInt(mincoin, maxcoin);
|
||||
if(*copper > cash) { *copper = cash; }
|
||||
cash -= *copper;
|
||||
if(*silver>(cash/10)) { *silver = (cash/10); }
|
||||
cash -= *silver*10;
|
||||
if(*gold > (cash/100)) { *gold = (cash/100); }
|
||||
cash -= *gold*100;
|
||||
}
|
||||
if (cash < 0) {
|
||||
cash = 0;
|
||||
}
|
||||
*plat = cash / 1000;
|
||||
cash -= *plat * 1000;
|
||||
uint32 gold2 = cash / 100;
|
||||
cash -= gold2 * 100;
|
||||
uint32 silver2 = cash / 10;
|
||||
cash -= silver2 * 10;
|
||||
*gold += gold2;
|
||||
*silver += silver2;
|
||||
*copper += cash;
|
||||
}
|
||||
|
||||
*gold = cash / 100;
|
||||
cash -= *gold * 100;
|
||||
|
||||
*silver = cash / 10;
|
||||
cash -= *silver * 10;
|
||||
|
||||
*copper = cash;
|
||||
}
|
||||
|
||||
// Do items
|
||||
@ -91,10 +82,10 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite
|
||||
|
||||
float drop_chance = 0.0f;
|
||||
if(ltchance > 0.0 && ltchance < 100.0) {
|
||||
drop_chance = MakeRandomFloat(0.0, 100.0);
|
||||
drop_chance = (float)MakeRandomFloat(0.0, 100.0);
|
||||
}
|
||||
|
||||
if (ltchance != 0.0 && (ltchance == 100.0 || drop_chance < ltchance)) {
|
||||
if (ltchance != 0.0 && (ltchance == 100.0 || drop_chance <= ltchance)) {
|
||||
AddLootDropToNPC(npc, lts->Entries[i].lootdrop_id, itemlist, droplimit, mindrop);
|
||||
}
|
||||
}
|
||||
@ -108,66 +99,79 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml
|
||||
if (!lds) {
|
||||
return;
|
||||
}
|
||||
if(lds->NumEntries == 0) //nothing possible to add
|
||||
|
||||
if(lds->NumEntries == 0)
|
||||
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++;
|
||||
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(MakeRandomFloat(0.0, 100.0) <= lds->Entries[i].chance) {
|
||||
const Item_Struct* 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);
|
||||
}
|
||||
}
|
||||
// Items with multipliers only count as 1 towards the limit.
|
||||
if(pickedcharges > 0)
|
||||
limit++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If true, limit reached.
|
||||
if(limit >= droplimit && droplimit > 0)
|
||||
if(lds->NumEntries > 100 && droplimit == 0) {
|
||||
droplimit = 10;
|
||||
}
|
||||
|
||||
if(droplimit < mindrop) {
|
||||
droplimit = mindrop;
|
||||
}
|
||||
|
||||
float roll_t = 0.0f;
|
||||
bool active_item_list = false;
|
||||
for(uint32 i = 0; i < lds->NumEntries; ++i) {
|
||||
const Item_Struct* db_item = GetItem(lds->Entries[i].item_id);
|
||||
if(db_item) {
|
||||
roll_t += lds->Entries[i].chance;
|
||||
active_item_list = true;
|
||||
}
|
||||
}
|
||||
|
||||
roll_t = EQEmu::ClampLower(roll_t, 100.0f);
|
||||
|
||||
if(!active_item_list) {
|
||||
return;
|
||||
}
|
||||
|
||||
mindrop = EQEmu::ClampLower(mindrop, (uint8)1);
|
||||
int item_count = MakeRandomInt(mindrop, droplimit);
|
||||
for(int i = 0; i < item_count; ++i) {
|
||||
float roll = (float)MakeRandomFloat(0.0, roll_t);
|
||||
for(uint32 j = 0; j < lds->NumEntries; ++j) {
|
||||
const Item_Struct* 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)MakeRandomFloat(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;
|
||||
|
||||
item++;
|
||||
i++;
|
||||
|
||||
// We didn't reach our minimium, run loop again.
|
||||
if(i == lds->NumEntries){
|
||||
if(limit < mindrop){
|
||||
i = 0;
|
||||
}
|
||||
else {
|
||||
roll -= lds->Entries[j].chance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // We either ran out of items or reached our limit.
|
||||
}
|
||||
|
||||
//if itemlist is null, just send wear changes
|
||||
@ -194,7 +198,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge
|
||||
}
|
||||
|
||||
item->item_id = item2->ID;
|
||||
item->charges = charges;
|
||||
item->charges = (uint8)charges;
|
||||
item->aug1 = 0;
|
||||
item->aug2 = 0;
|
||||
item->aug3 = 0;
|
||||
|
||||
@ -616,7 +616,7 @@ public:
|
||||
bool PassCastRestriction(bool UseCastRestriction = true, int16 value = 0, bool IsDamage = true);
|
||||
bool ImprovedTaunt();
|
||||
bool TryRootFadeByDamage(int buffslot, Mob* attacker);
|
||||
int16 GetSlowMitigation() const {return slow_mitigation;}
|
||||
float GetSlowMitigation() const { return slow_mitigation; }
|
||||
void CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster = nullptr);
|
||||
inline int16 GetSpellPowerDistanceMod() const { return SpellPowerDistanceMod; };
|
||||
inline void SetSpellPowerDistanceMod(int16 value) { SpellPowerDistanceMod = value; };
|
||||
|
||||
@ -257,7 +257,7 @@ public:
|
||||
|
||||
uint32 GetMaxDMG() const {return max_dmg;}
|
||||
uint32 GetMinDMG() const {return min_dmg;}
|
||||
int16 GetSlowMitigation() const {return slow_mitigation;}
|
||||
float GetSlowMitigation() const { return slow_mitigation; }
|
||||
float GetAttackSpeed() const {return attack_speed;}
|
||||
bool IsAnimal() const { return(bodytype == BT_Animal); }
|
||||
uint16 GetPetSpellID() const {return pet_spell_id;}
|
||||
|
||||
@ -2075,7 +2075,7 @@ XS(XS_NPC_GetSlowMitigation)
|
||||
Perl_croak(aTHX_ "Usage: NPC::GetSlowMitigation(THIS)");
|
||||
{
|
||||
NPC * THIS;
|
||||
int16 RETVAL;
|
||||
float RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "NPC")) {
|
||||
@ -2088,7 +2088,7 @@ XS(XS_NPC_GetSlowMitigation)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetSlowMitigation();
|
||||
XSprePUSH; PUSHn((UV)RETVAL);
|
||||
XSprePUSH; PUSHn((double)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user