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 "masterentity.h"
|
||||||
#include "zonedb.h"
|
#include "zonedb.h"
|
||||||
#include "../common/misc_functions.h"
|
#include "../common/misc_functions.h"
|
||||||
#ifdef _WINDOWS
|
#include "../common/data_verification.h"
|
||||||
#define snprintf _snprintf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Queries the loottable: adds item & coin to the npc
|
// 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) {
|
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;
|
*copper = 0;
|
||||||
*silver = 0;
|
*silver = 0;
|
||||||
*gold = 0;
|
*gold = 0;
|
||||||
@ -39,44 +37,37 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite
|
|||||||
if (!lts)
|
if (!lts)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// do coin
|
uint32 min_cash = lts->mincash;
|
||||||
if (lts->mincash > lts->maxcash) {
|
uint32 max_cash = lts->maxcash;
|
||||||
std::cerr << "Error in loottable #" << loottable_id << ": mincash > maxcash" << std::endl;
|
if(min_cash > max_cash) {
|
||||||
|
uint32 t = min_cash;
|
||||||
|
min_cash = max_cash;
|
||||||
|
max_cash = t;
|
||||||
}
|
}
|
||||||
else if (lts->maxcash != 0) {
|
|
||||||
uint32 cash = 0;
|
uint32 cash = 0;
|
||||||
if (lts->mincash == lts->maxcash)
|
if(max_cash > 0 && EQEmu::ValueWithin(lts->avgcoin, min_cash, max_cash)) {
|
||||||
cash = lts->mincash;
|
int avg_cash_roll = MakeRandomInt(1, 100);
|
||||||
else
|
if(avg_cash_roll > 50) {
|
||||||
cash = MakeRandomInt(lts->mincash, lts->maxcash);
|
cash = MakeRandomInt(lts->avgcoin, max_cash);
|
||||||
if (cash != 0) {
|
} else {
|
||||||
if (lts->avgcoin != 0) {
|
cash = MakeRandomInt(min_cash, lts->avgcoin);
|
||||||
//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;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
cash = MakeRandomInt(min_cash, max_cash);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cash != 0) {
|
||||||
|
*plat = cash / 1000;
|
||||||
|
cash -= *plat * 1000;
|
||||||
|
|
||||||
|
*gold = cash / 100;
|
||||||
|
cash -= *gold * 100;
|
||||||
|
|
||||||
|
*silver = cash / 10;
|
||||||
|
cash -= *silver * 10;
|
||||||
|
|
||||||
|
*copper = cash;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do items
|
// Do items
|
||||||
@ -91,11 +82,11 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite
|
|||||||
|
|
||||||
float drop_chance = 0.0f;
|
float drop_chance = 0.0f;
|
||||||
if(ltchance > 0.0 && ltchance < 100.0) {
|
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);
|
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) {
|
if (!lds) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(lds->NumEntries == 0) //nothing possible to add
|
|
||||||
|
if(lds->NumEntries == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Too long a list needs to be limited.
|
if(droplimit == 0 && mindrop == 0) {
|
||||||
if(lds->NumEntries > 99 && droplimit < 1)
|
for(uint32 i = 0; i < lds->NumEntries; ++i) {
|
||||||
droplimit = lds->NumEntries/100;
|
int charges = lds->Entries[i].multiplier;
|
||||||
|
for(int j = 0; j < charges; ++j) {
|
||||||
uint8 limit = 0;
|
if(MakeRandomFloat(0.0, 100.0) <= lds->Entries[i].chance) {
|
||||||
// Start at a random point in itemlist.
|
const Item_Struct* dbitem = GetItem(lds->Entries[i].item_id);
|
||||||
uint32 item = MakeRandomInt(0, lds->NumEntries-1);
|
npc->AddLootDrop(dbitem, itemlist, lds->Entries[i].item_charges, lds->Entries[i].minlevel,
|
||||||
// Main loop.
|
lds->Entries[i].maxlevel, lds->Entries[i].equip_item > 0 ? true : false, false);
|
||||||
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.
|
return;
|
||||||
if(pickedcharges > 0)
|
}
|
||||||
limit++;
|
|
||||||
|
|
||||||
// If true, limit reached.
|
if(lds->NumEntries > 100 && droplimit == 0) {
|
||||||
if(limit >= droplimit && droplimit > 0)
|
droplimit = 10;
|
||||||
break;
|
}
|
||||||
|
|
||||||
item++;
|
if(droplimit < mindrop) {
|
||||||
i++;
|
droplimit = mindrop;
|
||||||
|
}
|
||||||
|
|
||||||
// We didn't reach our minimium, run loop again.
|
float roll_t = 0.0f;
|
||||||
if(i == lds->NumEntries){
|
bool active_item_list = false;
|
||||||
if(limit < mindrop){
|
for(uint32 i = 0; i < lds->NumEntries; ++i) {
|
||||||
i = 0;
|
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;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
roll -= lds->Entries[j].chance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // We either ran out of items or reached our limit.
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if itemlist is null, just send wear changes
|
//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->item_id = item2->ID;
|
||||||
item->charges = charges;
|
item->charges = (uint8)charges;
|
||||||
item->aug1 = 0;
|
item->aug1 = 0;
|
||||||
item->aug2 = 0;
|
item->aug2 = 0;
|
||||||
item->aug3 = 0;
|
item->aug3 = 0;
|
||||||
|
|||||||
@ -616,7 +616,7 @@ public:
|
|||||||
bool PassCastRestriction(bool UseCastRestriction = true, int16 value = 0, bool IsDamage = true);
|
bool PassCastRestriction(bool UseCastRestriction = true, int16 value = 0, bool IsDamage = true);
|
||||||
bool ImprovedTaunt();
|
bool ImprovedTaunt();
|
||||||
bool TryRootFadeByDamage(int buffslot, Mob* attacker);
|
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);
|
void CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster = nullptr);
|
||||||
inline int16 GetSpellPowerDistanceMod() const { return SpellPowerDistanceMod; };
|
inline int16 GetSpellPowerDistanceMod() const { return SpellPowerDistanceMod; };
|
||||||
inline void SetSpellPowerDistanceMod(int16 value) { SpellPowerDistanceMod = value; };
|
inline void SetSpellPowerDistanceMod(int16 value) { SpellPowerDistanceMod = value; };
|
||||||
|
|||||||
@ -257,7 +257,7 @@ public:
|
|||||||
|
|
||||||
uint32 GetMaxDMG() const {return max_dmg;}
|
uint32 GetMaxDMG() const {return max_dmg;}
|
||||||
uint32 GetMinDMG() const {return min_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;}
|
float GetAttackSpeed() const {return attack_speed;}
|
||||||
bool IsAnimal() const { return(bodytype == BT_Animal); }
|
bool IsAnimal() const { return(bodytype == BT_Animal); }
|
||||||
uint16 GetPetSpellID() const {return pet_spell_id;}
|
uint16 GetPetSpellID() const {return pet_spell_id;}
|
||||||
|
|||||||
@ -2075,7 +2075,7 @@ XS(XS_NPC_GetSlowMitigation)
|
|||||||
Perl_croak(aTHX_ "Usage: NPC::GetSlowMitigation(THIS)");
|
Perl_croak(aTHX_ "Usage: NPC::GetSlowMitigation(THIS)");
|
||||||
{
|
{
|
||||||
NPC * THIS;
|
NPC * THIS;
|
||||||
int16 RETVAL;
|
float RETVAL;
|
||||||
dXSTARG;
|
dXSTARG;
|
||||||
|
|
||||||
if (sv_derived_from(ST(0), "NPC")) {
|
if (sv_derived_from(ST(0), "NPC")) {
|
||||||
@ -2088,7 +2088,7 @@ XS(XS_NPC_GetSlowMitigation)
|
|||||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||||
|
|
||||||
RETVAL = THIS->GetSlowMitigation();
|
RETVAL = THIS->GetSlowMitigation();
|
||||||
XSprePUSH; PUSHn((UV)RETVAL);
|
XSprePUSH; PUSHn((double)RETVAL);
|
||||||
}
|
}
|
||||||
XSRETURN(1);
|
XSRETURN(1);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user