[Zone] Convert Fishing/Foraging to Repositories (#4008)

* [Zone] Convert Fishing/Foraging to Repositories

# Notes
- Convert `LoadFishing()` and `LoadForage()` to repositories.

* Update forage.cpp

* Cleanup
This commit is contained in:
Alex King 2024-01-30 05:55:09 -05:00 committed by GitHub
parent bc59882a65
commit ae79022e06
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 108 additions and 102 deletions

View File

@ -31,6 +31,8 @@
#include "water_map.h" #include "water_map.h"
#include "zonedb.h" #include "zonedb.h"
#include "../common/repositories/criteria/content_filter_criteria.h" #include "../common/repositories/criteria/content_filter_criteria.h"
#include "../common/repositories/forage_repository.h"
#include "../common/repositories/fishing_repository.h"
#include "../common/events/player_event_logs.h" #include "../common/events/player_event_logs.h"
#include "worldserver.h" #include "worldserver.h"
@ -46,141 +48,145 @@ struct NPCType;
//for a given zone. //for a given zone.
#define FORAGE_ITEM_LIMIT 50 #define FORAGE_ITEM_LIMIT 50
uint32 ZoneDatabase::GetZoneForage(uint32 ZoneID, uint8 skill) { uint32 ZoneDatabase::LoadForage(uint32 zone_id, uint8 skill_level)
{
uint32 forage_items[FORAGE_ITEM_LIMIT];
uint32 item[FORAGE_ITEM_LIMIT]; for (uint16 slot_id = 0; slot_id < FORAGE_ITEM_LIMIT; slot_id++) {
uint32 chance[FORAGE_ITEM_LIMIT]; forage_items[slot_id] = 0;
uint32 ret;
for (int c=0; c < FORAGE_ITEM_LIMIT; c++) {
item[c] = 0;
} }
uint32 chancepool = 0; const auto& l = ForageRepository::GetWhere(
std::string query = fmt::format( *this,
SQL( fmt::format(
SELECT "(`zoneid` = {} || `zoneid` = 0) AND `level` <= {} {} LIMIT {}",
itemid, zone_id,
chance skill_level,
FROM ContentFilterCriteria::apply(),
forage FORAGE_ITEM_LIMIT
WHERE )
zoneid = '{}'
and level <= '{}'
{}
LIMIT
{}
),
ZoneID,
skill,
ContentFilterCriteria::apply(),
FORAGE_ITEM_LIMIT
); );
auto results = QueryDatabase(query);
if (!results.Success()) { if (l.empty()) {
return 0; return 0;
} }
uint8 index = 0; LogInfo(
for (auto row = results.begin(); row != results.end(); ++row, ++index) { "Loaded [{}] Forage Item{}",
if (index >= FORAGE_ITEM_LIMIT) { Strings::Commify(l.size()),
l.size() != 1 ? "s" : ""
);
int forage_chances[FORAGE_ITEM_LIMIT];
int current_chance = 0;
uint32 item_id = 0;
uint8 count = 0;
for (const auto& e : l) {
if (count >= FORAGE_ITEM_LIMIT) {
break; break;
} }
item[index] = Strings::ToInt(row[0]); forage_items[count] = e.Itemid;
chance[index] = Strings::ToInt(row[1]) + chancepool; forage_chances[count] = e.chance;
chancepool = chance[index];
current_chance = forage_chances[count];
count++;
} }
if(chancepool == 0 || index < 1) if (current_chance == 0 || count < 1) {
return 0; return 0;
if(index == 1) {
return item[0];
} }
ret = 0; if (count == 1) {
return forage_items[0];
}
uint32 rindex = zone->random.Int(1, chancepool); const int roll = zone->random.Int(1, current_chance);
for(int i = 0; i < index; i++) { for (uint16 slot_id = 0; slot_id < count; slot_id++) {
if(rindex <= chance[i]) { if (roll <= forage_chances[slot_id]) {
ret = item[i]; item_id = forage_items[slot_id];
break; break;
} }
} }
return ret; return item_id;
} }
uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id, uint8 &npc_chance) uint32 ZoneDatabase::LoadFishing(uint32 zone_id, uint8 skill_level, uint32 &npc_id, uint8 &npc_chance)
{ {
uint32 item[50]; uint32 fishing_items[50];
uint32 chance[50]; int fishing_chances[50];
uint32 npc_ids[50];
uint32 npc_chances[50];
uint32 chancepool = 0;
uint32 ret = 0;
for (int c=0; c<50; c++) { for (uint16 slot_id = 0; slot_id < 50; slot_id++) {
item[c]=0; fishing_items[slot_id] = 0;
chance[c]=0; fishing_chances[slot_id] = 0;
} }
std::string query = fmt::format( const auto& l = FishingRepository::GetWhere(
SQL( *this,
SELECT fmt::format(
itemid, "(`zoneid` = {} || `zoneid` = 0) AND `skill_level` <= {} {}",
chance, zone_id,
npc_id, skill_level,
npc_chance ContentFilterCriteria::apply()
FROM )
fishing
WHERE
(zoneid = '{}' || zoneid = 0)
AND skill_level <= '{}'
{}
),
ZoneID,
skill,
ContentFilterCriteria::apply()
); );
auto results = QueryDatabase(query);
if (!results.Success()) { if (l.empty()) {
return 0; return 0;
} }
uint8 index = 0; LogInfo(
for (auto row = results.begin(); row != results.end(); ++row, ++index) { "Loaded [{}] Fishing Item{}",
if (index >= 50) Strings::Commify(l.size()),
break; l.size() != 1 ? "s" : ""
);
item[index] = Strings::ToInt(row[0]); uint32 npc_ids[50];
chance[index] = Strings::ToInt(row[1])+chancepool; uint32 npc_chances[50];
chancepool = chance[index];
npc_ids[index] = Strings::ToInt(row[2]); int current_chance = 0;
npc_chances[index] = Strings::ToInt(row[3]); uint32 item_id = 0;
} uint8 count = 0;
npc_id = 0; for (const auto &e: l) {
if (count >= 50) {
break;
}
fishing_items[count] = e.Itemid;
fishing_chances[count] = e.chance + current_chance;
npc_ids[count] = e.npc_id;
npc_chances[count] = e.npc_chance;
current_chance = fishing_chances[count];
}
npc_id = 0;
npc_chance = 0; npc_chance = 0;
if (index <= 0)
return 0;
uint32 random = zone->random.Int(1, chancepool); if (count <= 0) {
for (int i = 0; i < index; i++) return 0;
{ }
if (random > chance[i])
continue;
ret = item[i]; const int roll = zone->random.Int(1, current_chance);
npc_id = npc_ids[i];
npc_chance = npc_chances[i];
break;
}
return ret; for (uint16 i = 0; i < count; i++) {
if (roll > fishing_chances[i]) {
continue;
}
item_id = fishing_items[i];
npc_id = npc_ids[i];
npc_chance = npc_chances[i];
break;
}
return item_id;
} }
//we need this function to immediately determine, after we receive OP_Fishing, if we can even try to fish, otherwise we have to wait a while to get the failure //we need this function to immediately determine, after we receive OP_Fishing, if we can even try to fish, otherwise we have to wait a while to get the failure
@ -307,7 +313,7 @@ void Client::GoFish()
if (zone->random.Int(0, 399) <= fishing_skill ) { if (zone->random.Int(0, 399) <= fishing_skill ) {
uint32 npc_id = 0; uint32 npc_id = 0;
uint8 npc_chance = 0; uint8 npc_chance = 0;
food_id = content_db.GetZoneFishing(m_pp.zone_id, fishing_skill, npc_id, npc_chance); food_id = content_db.LoadFishing(m_pp.zone_id, fishing_skill, npc_id, npc_chance);
//check for add NPC //check for add NPC
if (npc_chance > 0 && npc_id) { if (npc_chance > 0 && npc_id) {
@ -452,7 +458,7 @@ void Client::ForageItem(bool guarantee) {
uint32 stringid = FORAGE_NOEAT; uint32 stringid = FORAGE_NOEAT;
if (zone->random.Roll(RuleI(Zone, ForageChance))) { if (zone->random.Roll(RuleI(Zone, ForageChance))) {
foragedfood = content_db.GetZoneForage(m_pp.zone_id, skill_level); foragedfood = content_db.LoadForage(m_pp.zone_id, skill_level);
} }
//not an else in case theres no DB food //not an else in case theres no DB food

View File

@ -598,8 +598,8 @@ public:
/* Tradeskills */ /* Tradeskills */
bool GetTradeRecipe(const EQ::ItemInstance* container, uint8 c_type, uint32 some_id, Client* c, DBTradeskillRecipe_Struct* spec, bool* is_augmented); bool GetTradeRecipe(const EQ::ItemInstance* container, uint8 c_type, uint32 some_id, Client* c, DBTradeskillRecipe_Struct* spec, bool* is_augmented);
bool GetTradeRecipe(uint32 recipe_id, uint8 c_type, uint32 some_id, Client* c, DBTradeskillRecipe_Struct* spec); bool GetTradeRecipe(uint32 recipe_id, uint8 c_type, uint32 some_id, Client* c, DBTradeskillRecipe_Struct* spec);
uint32 GetZoneForage(uint32 ZoneID, uint8 skill); /* for foraging */ uint32 LoadForage(uint32 zone_id, uint8 skill_level);
uint32 GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id, uint8 &npc_chance); uint32 LoadFishing(uint32 zone_id, uint8 skill_level, uint32 &npc_id, uint8 &npc_chance);
void UpdateRecipeMadecount(uint32 recipe_id, uint32 char_id, uint32 madecount); void UpdateRecipeMadecount(uint32 recipe_id, uint32 char_id, uint32 madecount);
bool EnableRecipe(uint32 recipe_id); bool EnableRecipe(uint32 recipe_id);
bool DisableRecipe(uint32 recipe_id); bool DisableRecipe(uint32 recipe_id);