Merge pull request #1094 from EQEmu/integration/multi-tenancy-expansions-repository

Integration/multi tenancy expansions repository
This commit is contained in:
Chris Miles
2020-07-30 22:27:58 -05:00
committed by GitHub
433 changed files with 235394 additions and 2397 deletions
+4 -1
View File
@@ -142,6 +142,7 @@ SET(zone_sources
zone_config.cpp
zonedb.cpp
zone_reload.cpp
zone_store.cpp
zoning.cpp
)
@@ -249,7 +250,9 @@ SET(zone_headers
zone_config.h
zonedb.h
zonedump.h
zone_reload.h )
zone_reload.h
zone_store.h
)
ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers})
+6 -5
View File
@@ -33,6 +33,7 @@ Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
#include "string_ids.h"
#include "titles.h"
#include "zonedb.h"
#include "zone_store.h"
extern QueryServ* QServ;
@@ -55,7 +56,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
}
PetRecord record;
if (!database.GetPoweredPetEntry(spells[spell_id].teleport_zone, act_power, &record))
if (!content_db.GetPoweredPetEntry(spells[spell_id].teleport_zone, act_power, &record))
{
LogError("Unknown swarm pet spell id: {}, check pets table", spell_id);
Message(Chat::Red, "Unable to find data for pet %s", spells[spell_id].teleport_zone);
@@ -81,7 +82,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
NPCType *made_npc = nullptr;
const NPCType *npc_type = database.LoadNPCTypesData(pet.npc_id);
const NPCType *npc_type = content_db.LoadNPCTypesData(pet.npc_id);
if (npc_type == nullptr) {
//log write
LogError("Unknown npc type for swarm pet spell id: [{}]", spell_id);
@@ -186,7 +187,7 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid
NPCType *made_npc = nullptr;
const NPCType *npc_type = database.LoadNPCTypesData(typesid);
const NPCType *npc_type = content_db.LoadNPCTypesData(typesid);
if(npc_type == nullptr) {
//log write
LogError("Unknown npc type for swarm pet type id: [{}]", typesid);
@@ -281,7 +282,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
return;
//assuming we have pets in our table; we take the first pet as a base type.
const NPCType *base_type = database.LoadNPCTypesData(500);
const NPCType *base_type = content_db.LoadNPCTypesData(500);
auto make_npc = new NPCType;
memcpy(make_npc, base_type, sizeof(NPCType));
@@ -1595,7 +1596,7 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price,
void Zone::LoadAlternateAdvancement() {
LogInfo("Loading Alternate Advancement Data");
if(!database.LoadAlternateAdvancementAbilities(aa_abilities,
if(!content_db.LoadAlternateAdvancementAbilities(aa_abilities,
aa_ranks))
{
aa_abilities.clear();
+2 -2
View File
@@ -62,7 +62,7 @@ void EntityList::DescribeAggro(Client *towho, NPC *from_who, float d, bool verbo
} else if(my_primary < 0) {
strcpy(namebuf, "(Special faction)");
} else {
if(!database.GetFactionName(my_primary, namebuf, sizeof(namebuf)))
if(!content_db.GetFactionName(my_primary, namebuf, sizeof(namebuf)))
strcpy(namebuf, "(Unknown)");
}
towho->Message(Chat::White, ".. I am on faction %s (%d)\n", namebuf, my_primary);
@@ -171,7 +171,7 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
towho->Message(Chat::White, "...%s is on special faction %d", mob->GetName(), mob_primary);
} else {
char namebuf[256];
if(!database.GetFactionName(mob_primary, namebuf, sizeof(namebuf)))
if(!content_db.GetFactionName(mob_primary, namebuf, sizeof(namebuf)))
strcpy(namebuf, "(Unknown)");
std::list<struct NPCFaction*>::iterator cur,end;
cur = faction_list.begin();
+1
View File
@@ -22,6 +22,7 @@
#include "../common/net/websocket_server.h"
#include "../common/eqemu_logsys.h"
#include "zonedb.h"
#include "zone_store.h"
#include "client.h"
#include "entity.h"
#include "corpse.h"
+13 -12
View File
@@ -283,7 +283,7 @@ bool Mob::CheckHitChance(Mob* other, DamageHitInfo &hit)
bool lua_ret = false;
bool ignoreDefault = false;
lua_ret = LuaParser::Instance()->CheckHitChance(this, other, hit, ignoreDefault);
if(ignoreDefault) {
return lua_ret;
}
@@ -323,7 +323,7 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit)
bool lua_ret = false;
bool ignoreDefault = false;
lua_ret = LuaParser::Instance()->AvoidDamage(this, other, hit, ignoreDefault);
if (ignoreDefault) {
return lua_ret;
}
@@ -862,6 +862,7 @@ int Mob::ACSum(bool skip_caps)
int Mob::GetBestMeleeSkill()
{
int bestSkill=0;
EQ::skills::SkillType meleeSkills[]=
{ EQ::skills::Skill1HBlunt,
EQ::skills::Skill1HSlashing,
@@ -879,7 +880,7 @@ int Mob::GetBestMeleeSkill()
value = GetSkill(meleeSkills[i]);
bestSkill = std::max(value, bestSkill);
}
return bestSkill;
}
@@ -892,7 +893,7 @@ int Mob::offense(EQ::skills::SkillType skill)
case EQ::skills::SkillArchery:
case EQ::skills::SkillThrowing:
stat_bonus = GetDEX();
break;
break;
// Mobs with no weapons default to H2H.
// Since H2H is capped at 100 for many many classes,
@@ -943,7 +944,7 @@ void Mob::MeleeMitigation(Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions
#ifdef LUA_EQEMU
bool ignoreDefault = false;
LuaParser::Instance()->MeleeMitigation(this, attacker, hit, opts, ignoreDefault);
if (ignoreDefault) {
return;
}
@@ -1735,7 +1736,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQ::skills::Skill
if (!RuleB(Character, UseDeathExpLossMult)) {
exploss = (int)(GetLevel() * (GetLevel() / 18.0) * 12000);
}
if (RuleB(Zone, LevelBasedEXPMods)) {
// Death in levels with xp_mod (such as hell levels) was resulting
// in losing more that appropriate since the loss was the same but
@@ -1893,7 +1894,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQ::skills::Skill
dead_timer.Start(5000, true);
m_pp.zone_id = m_pp.binds[0].zoneId;
m_pp.zoneInstance = m_pp.binds[0].instance_id;
database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(m_pp.zone_id));
database.MoveCharacterToZone(this->CharacterID(), m_pp.zone_id);
Save();
GoToDeath();
}
@@ -2452,7 +2453,7 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQ::skills::SkillTy
bool allow_merchant_corpse = RuleB(Merchant, AllowCorpse);
bool is_merchant = (class_ == MERCHANT || class_ == ADVENTUREMERCHANT || MerchantType != 0);
if (!HasOwner() && !IsMerc() && !GetSwarmInfo() && (!is_merchant || allow_merchant_corpse) &&
((killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) ||
(killer->IsNPC() && killer->CastToNPC()->GetSwarmInfo() && killer->CastToNPC()->GetSwarmInfo()->GetOwner() && killer->CastToNPC()->GetSwarmInfo()->GetOwner()->IsClient())))
@@ -4093,7 +4094,7 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon,
if (IsPet() && hand != EQ::invslot::slotPrimary) //Pets can only proc spell procs from their primay hand (ie; beastlord pets)
continue; // If pets ever can proc from off hand, this will need to change
if (SpellProcs[i].base_spellID == POISON_PROC &&
if (SpellProcs[i].base_spellID == POISON_PROC &&
(!weapon || weapon->ItemType != EQ::item::ItemType1HPiercing))
continue; // Old school poison will only proc with 1HP equipped.
@@ -4113,7 +4114,7 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon,
// Spell procs (buffs)
if (SpellProcs[i].spellID != SPELL_UNKNOWN) {
if (SpellProcs[i].base_spellID == POISON_PROC) {
poison_slot=i;
poison_slot=i;
continue; // Process the poison proc last per @mackal
}
@@ -4160,7 +4161,7 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon,
RemoveProcFromWeapon(spell_id);
}
}
}
}
if (HasSkillProcs() && hand != EQ::invslot::slotRange) { //We check ranged skill procs within the attack functions.
uint16 skillinuse = 28;
@@ -4696,7 +4697,7 @@ void Mob::ApplyDamageTable(DamageHitInfo &hit)
#ifdef LUA_EQEMU
bool ignoreDefault = false;
LuaParser::Instance()->ApplyDamageTable(this, hit, ignoreDefault);
if (ignoreDefault) {
return;
}
+2 -2
View File
@@ -837,7 +837,7 @@ void Mob::MakeAura(uint16 spell_id)
}
AuraRecord record{};
if (!database.GetAuraEntry(spell_id, record)) {
if (!content_db.GetAuraEntry(spell_id, record)) {
Message(Chat::Red, "Unable to find data for aura %s", spells[spell_id].name);
LogError("Unable to find data for aura [{}], check auras table", spell_id);
return;
@@ -871,7 +871,7 @@ void Mob::MakeAura(uint16 spell_id)
return;
}
const auto base = database.LoadNPCTypesData(record.npc_type);
const auto base = content_db.LoadNPCTypesData(record.npc_type);
if (base == nullptr) {
Message(Chat::Red, "Unable to load NPC data for aura %s", spells[spell_id].teleport_zone);
LogError(
+7 -6
View File
@@ -29,6 +29,7 @@
#include "groups.h"
#include "corpse.h"
#include "zonedb.h"
#include "zone_store.h"
#include "string_ids.h"
#include "../common/misc_functions.h"
#include "../common/global_define.h"
@@ -320,7 +321,7 @@ public:
void SetStopMeleeLevel(uint8 level);
void SetGuardMode();
void SetHoldMode();
// Mob AI Virtual Override Methods
virtual void AI_Process();
virtual void AI_Stop();
@@ -351,7 +352,7 @@ public:
virtual void UpdateEquipmentLight() { m_Light.Type[EQ::lightsource::LightEquipment] = m_inv.FindBrightestLightType(); m_Light.Level[EQ::lightsource::LightEquipment] = EQ::lightsource::TypeToLevel(m_Light.Type[EQ::lightsource::LightEquipment]); }
const EQ::InventoryProfile& GetBotInv() const { return m_inv; }
// Static Class Methods
// Static Class Methods
//static void DestroyBotRaidObjects(Client* client); // Can be removed after bot raids are dumped
static Bot* LoadBot(uint32 botID);
static uint32 SpawnedBotCount(uint32 botOwnerCharacterID);
@@ -405,7 +406,7 @@ public:
static BotSpell GetDebuffBotSpell(Bot* botCaster, Mob* target);
static BotSpell GetBestBotSpellForCure(Bot* botCaster, Mob* target);
static BotSpell GetBestBotSpellForResistDebuff(Bot* botCaster, Mob* target);
static NPCType *CreateDefaultNPCTypeStructForBot(std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender);
// Static Bot Group Methods
@@ -451,7 +452,7 @@ public:
bool IsBotNonSpellFighter() { return IsNonSpellFighterClass(GetClass()); }
bool CanHeal();
int GetRawACNoShield(int &shield_ac);
// new heal rotation code
bool CreateHealRotation(uint32 cycle_duration_ms = 5000, bool fast_heals = false, bool adaptive_targeting = false, bool casting_override = false);
bool DestroyHealRotation();
@@ -597,7 +598,7 @@ public:
int32 GetBasePR() { return _basePR; }
int32 GetBaseDR() { return _baseDR; }
int32 GetBaseCorrup() { return _baseCorrup; }
protected:
virtual void PetAIProcess();
virtual void BotMeditate(bool isSitting);
@@ -656,7 +657,7 @@ private:
int32 max_end;
int32 end_regen;
uint32 timers[MaxTimer];
Timer m_evade_timer; // can be moved to pTimers at some point
Timer m_alt_combat_hate_timer;
Timer m_auto_defend_timer;
+107 -106
View File
@@ -24,7 +24,7 @@
2. Add the function in this file.
3. In the bot_command_init function you must add a call to bot_command_add
for your function.
Notes: If you want an alias for your bot command, add an entry to the
`bot_command_settings` table in your database. The access level you
set with bot_command_add is the default setting if the bot command isn't
@@ -60,6 +60,7 @@
#include "bot_command.h"
#include "zonedb.h"
#include "zone_store.h"
#include "guild_mgr.h"
#include "map.h"
#include "doors.h"
@@ -120,18 +121,18 @@ public:
static void Load() {
bot_command_spells.clear();
bcst_levels_map bot_levels_map;
for (int i = BCEnum::SpellTypeFirst; i <= BCEnum::SpellTypeLast; ++i) {
bot_command_spells[static_cast<BCEnum::SpType>(i)];
bot_levels_map[static_cast<BCEnum::SpType>(i)];
}
for (int spell_id = 2; spell_id < SPDAT_RECORDS; ++spell_id) {
if (spells[spell_id].player_1[0] == '\0')
continue;
if (spells[spell_id].targettype != ST_Target && spells[spell_id].CastRestriction != 0) // watch
continue;
auto target_type = BCEnum::TT_None;
switch (spells[spell_id].targettype) {
case ST_GroupTeleport:
@@ -196,7 +197,7 @@ public:
}
if (target_type == BCEnum::TT_None)
continue;
uint8 class_levels[16] = { 0 };
bool player_spell = false;
for (int class_type = WARRIOR; class_type <= BERSERKER; ++class_type) {
@@ -209,7 +210,7 @@ public:
}
if (!player_spell)
continue;
STBaseEntry* entry_prototype = nullptr;
while (true) {
switch (spells[spell_id].effectid[EFFECTIDTOINDEX(1)]) {
@@ -310,7 +311,7 @@ public:
}
if (entry_prototype)
break;
switch (spells[spell_id].effectid[EFFECTIDTOINDEX(2)]) {
case SE_Succor:
entry_prototype = new STEscapeEntry;
@@ -334,7 +335,7 @@ public:
}
if (entry_prototype)
break;
while (spells[spell_id].typedescnum == 27) {
if (!spells[spell_id].goodEffect)
break;
@@ -351,7 +352,7 @@ public:
}
if (entry_prototype)
break;
switch (spells[spell_id].SpellAffectIndex) {
case 1: {
bool valid_spell = false;
@@ -453,7 +454,7 @@ public:
}
if (!entry_prototype)
continue;
if (target_type == BCEnum::TT_Self && (entry_prototype->BCST() != BCEnum::SpT_Stance && entry_prototype->BCST() != BCEnum::SpT_SummonCorpse)) {
#ifdef BCSTSPELLDUMP
LogError("DELETING entry_prototype (primary clause) - name: [{}], target_type: [{}], BCST: [{}]",
@@ -532,12 +533,12 @@ public:
spell_entry = new STBaseEntry(entry_prototype);
break;
}
assert(spell_entry);
spell_entry->caster_class = class_type;
spell_entry->spell_level = class_levels[class_index];
bot_command_spells[spell_entry->BCST()].push_back(spell_entry);
if (bot_levels.find(class_type) == bot_levels.end() || bot_levels[class_type] > class_levels[class_index])
@@ -546,7 +547,7 @@ public:
delete(entry_prototype);
}
remove_inactive();
order_all();
load_teleport_zone_names();
@@ -1061,7 +1062,7 @@ private:
return;
std::string query = "SELECT `short_name`, `long_name` FROM `zone` WHERE '' NOT IN (`short_name`, `long_name`)";
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
LogError("load_teleport_zone_names() - Error in zone names query: [{}]", results.ErrorMessage().c_str());
return;
@@ -1152,7 +1153,7 @@ private:
auto bcst_id = static_cast<BCEnum::SpType>(i);
spell_dump << StringFormat("BCSpells::spell_dump(): - '%s' returned %u spells:\n",
BCEnum::SpellTypeEnumToString(bcst_id).c_str(), bot_command_spells[bcst_id].size());
bcst_list& map_entry = bot_command_spells[bcst_id];
for (auto list_iter = map_entry.begin(); list_iter != map_entry.end(); ++list_iter) {
STBaseEntry* list_entry = *list_iter;
@@ -1229,7 +1230,7 @@ private:
spell_dump << "\n";
++entry_count;
}
spell_dump << StringFormat("required_bots_map[%s] = \"%s\"\n",
BCEnum::SpellTypeEnumToString(static_cast<BCEnum::SpType>(i)).c_str(), required_bots_map[static_cast<BCEnum::SpType>(i)].c_str());
@@ -1477,7 +1478,7 @@ int bot_command_init(void)
working_bcl_iter.first.c_str()
);
}
continue;
}
@@ -1487,7 +1488,7 @@ int bot_command_init(void)
working_bcl_iter.first.c_str(),
bcs_iter->second.first
);
if (bcs_iter->second.second.empty()) {
continue;
}
@@ -1522,11 +1523,11 @@ int bot_command_init(void)
LogInfo("Failed to process 'Injected Bot Commands' update operation.");
}
}
bot_command_dispatch = bot_command_real_dispatch;
BCSpells::Load();
return bot_command_count;
}
@@ -1710,10 +1711,10 @@ namespace MyBots
auto test_bot = my_bot->CastToBot();
if (!test_bot->GetOwner() || !test_bot->GetOwner()->IsClient() || test_bot->GetOwner()->CastToClient() != bot_owner)
return false;
return true;
}
static bool IsMyBotInTargetsGroup(Client *bot_owner, Mob *grouped_bot) {
if (!bot_owner || !grouped_bot || !grouped_bot->GetGroup() || !IsMyBot(bot_owner, grouped_bot))
return false;
@@ -1724,7 +1725,7 @@ namespace MyBots
if (!target_mob->GetGroup() || (!target_mob->IsClient() && !target_mob->IsBot()))
return false;
return (grouped_bot->GetGroup() == target_mob->GetGroup());
}
@@ -1757,7 +1758,7 @@ namespace MyBots
sbl.clear();
if (!bot_owner || !name)
return;
auto selectable_bot_list = entity_list.GetBotsByBotOwnerCharacterID(bot_owner->CharacterID());
for (auto bot_iter : selectable_bot_list) {
if (!strcasecmp(bot_iter->GetCleanName(), name)) {
@@ -1765,7 +1766,7 @@ namespace MyBots
return;
}
}
if (!clear_list)
UniquifySBL(sbl);
}
@@ -1785,7 +1786,7 @@ namespace MyBots
if (IsMyBot(bot_owner, member_iter))
sbl.push_back(member_iter);
}
if (!clear_list)
UniquifySBL(sbl);
}
@@ -1806,7 +1807,7 @@ namespace MyBots
if (IsMyBot(bot_owner, member_iter))
sbl.push_back(member_iter);
}
if (!clear_list)
UniquifySBL(sbl);
}
@@ -1835,11 +1836,11 @@ namespace MyBots
if (IsMyBot(bot_owner, member_iter))
sbl.push_back(member_iter);
}
if (!clear_list)
UniquifySBL(sbl);
}
static void PopulateSBL_ByHealRotation(Client *bot_owner, std::list<Bot*> &sbl, const char* name, bool clear_list = true) {
if (clear_list)
sbl.clear();
@@ -1890,11 +1891,11 @@ namespace MyBots
if (IsMyBot(bot_owner, hrm_iter))
sbl.push_back(hrm_iter);
}
if (!clear_list)
UniquifySBL(sbl);
}
static void PopulateSBL_ByHealRotationTargets(Client *bot_owner, std::list<Bot*> &sbl, const char* name, bool clear_list = true) {
if (clear_list)
sbl.clear();
@@ -1915,7 +1916,7 @@ namespace MyBots
if (IsMyBot(bot_owner, hrm_iter))
sbl.push_back(static_cast<Bot*>(hrm_iter));
}
if (!clear_list)
UniquifySBL(sbl);
}
@@ -2461,7 +2462,7 @@ namespace ActionableBots
sbl.remove_if([bot_owner](Bot* l) { return (!MyBots::IsMyBot(bot_owner, l)); });
sbl.remove_if([bot_owner](Bot* l) { return (!l->IsBotArcher()); });
}
static void Filter_ByHighestSkill(Client* bot_owner, std::list<Bot*>& sbl, EQ::skills::SkillType skill_type, float& skill_value) {
sbl.remove_if([bot_owner](Bot* l) { return (!MyBots::IsMyBot(bot_owner, l)); });
skill_value = 0.0f;
@@ -2610,7 +2611,7 @@ void bot_command_apply_poison(Client *c, const Seperator *sep)
c->Message(m_fail, "Your rogue bot must be level 18 before %s can apply poison!", (my_rogue_bot->GetGender() == 1 ? "she" : "he"));
return;
}
const auto poison_instance = c->GetInv().GetItem(EQ::invslot::slotCursor);
if (!poison_instance) {
@@ -2748,7 +2749,7 @@ void bot_command_attack(Client *c, const Seperator *sep)
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(m_usage, "usage: <enemy_target> %s [actionable: byname | ownergroup | botgroup | namesgroup | healrotation | default: spawned] ([actionable_name])", sep->arg[0]);
return;
}
@@ -2756,7 +2757,7 @@ void bot_command_attack(Client *c, const Seperator *sep)
Mob* target_mob = ActionableTarget::AsSingle_ByAttackable(c);
if (!target_mob) {
c->Message(m_fail, "You must <target> an enemy to use this command");
return;
}
@@ -2765,7 +2766,7 @@ void bot_command_attack(Client *c, const Seperator *sep)
if (ab_arg.empty()) {
ab_arg = "spawned";
}
std::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, ab_arg.c_str(), sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) {
return;
@@ -2831,7 +2832,7 @@ void bot_command_bind_affinity(Client *c, const Seperator *sep)
c->Message(m_fail, "Failed to bind %s to this location", target_mob->GetCleanName());
break;
}
helper_no_available_bots(c, my_bot);
}
@@ -2866,7 +2867,7 @@ void bot_command_bot(Client *c, const Seperator *sep)
"botlist", "botoutofcombat", "botreport", "botspawn", "botstance", "botsummon", "bottogglearcher", "bottogglehelm", "botupdate"
};
*/
if (helper_command_alias_fail(c, "bot_command_bot", sep->arg[0], "bot"))
return;
@@ -2890,7 +2891,7 @@ void bot_command_botgroup(Client *c, const Seperator *sep)
"botgroupaddmember", "botgroupcreate", "botgroupdelete", "botgrouplist", "botgroupload", "botgroupremovemember"
};
*/
if (helper_command_alias_fail(c, "bot_command_botgroup", sep->arg[0], "botgroup"))
return;
@@ -2946,7 +2947,7 @@ void bot_command_charm(Client *c, const Seperator *sep)
break;
}
helper_no_available_bots(c, my_bot);
}
@@ -3016,7 +3017,7 @@ void bot_command_cure(Client *c, const Seperator *sep)
cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id);
break;
}
helper_no_available_bots(c, my_bot);
}
@@ -3031,7 +3032,7 @@ void bot_command_defensive(Client *c, const Seperator *sep)
return;
}
const int ab_mask = ActionableBots::ABM_Type1;
std::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None)
return;
@@ -3127,7 +3128,7 @@ void bot_command_depart(Client *c, const Seperator *sep)
cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id);
break;
}
helper_no_available_bots(c, my_bot);
}
@@ -3170,7 +3171,7 @@ void bot_command_escape(Client *c, const Seperator *sep)
cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id);
break;
}
helper_no_available_bots(c, my_bot);
}
@@ -3182,7 +3183,7 @@ void bot_command_find_aliases(Client *c, const Seperator *sep)
c->Message(m_usage, "usage: %s [alias | command]", sep->arg[0]);
return;
}
auto find_iter = bot_command_aliases.find(sep->arg[1]);
if (find_iter == bot_command_aliases.end()) {
c->Message(m_fail, "No bot commands or aliases match '%s'", sep->arg[1]);
@@ -3248,7 +3249,7 @@ void bot_command_follow(Client *c, const Seperator *sep)
std::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[name_arg]) == ActionableBots::ABT_None)
return;
sbl.remove(nullptr);
for (auto bot_iter : sbl) {
bot_iter->WipeHateList();
@@ -3366,7 +3367,7 @@ void bot_command_heal_rotation(Client *c, const Seperator *sep)
subcommand_list.push_back("healrotationstart");
subcommand_list.push_back("healrotationstop");
/* VS2012 code - end */
/* VS2013 code
const std::list<const char*> subcommand_list = {
"healrotationadaptivetargeting", "healrotationaddmember", "healrotationaddtarget", "healrotationadjustcritical", "healrotationadjustsafe",
@@ -3375,7 +3376,7 @@ void bot_command_heal_rotation(Client *c, const Seperator *sep)
"healrotationresetlimits", "healrotationsethot", "healrotationstart", "healrotationstop"
};
*/
if (helper_command_alias_fail(c, "bot_command_heal_rotation", sep->arg[0], "healrotation"))
return;
@@ -3401,7 +3402,7 @@ void bot_command_help(Client *c, const Seperator *sep)
{
if (helper_command_alias_fail(c, "bot_command_help", sep->arg[0], "help"))
return;
c->Message(m_message, "Available EQEMu bot commands:");
int bot_commands_shown = 0;
@@ -3505,7 +3506,7 @@ void bot_command_identify(Client *c, const Seperator *sep)
cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id);
break;
}
helper_no_available_bots(c, my_bot);
}
@@ -3581,7 +3582,7 @@ void bot_command_invisibility(Client *c, const Seperator *sep)
cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id);
break;
}
helper_no_available_bots(c, my_bot);
}
@@ -3647,7 +3648,7 @@ void bot_command_item_use(Client* c, const Seperator* sep)
msg = StringFormat("%cinventorygive byname %s", BOT_COMMAND_CHAR, bot_iter->GetCleanName());
text_link = bot_iter->CreateSayLink(c, msg.c_str(), bot_iter->GetCleanName());
for (auto slot_iter : equipable_slot_list) {
// needs more failure criteria - this should cover the bulk for now
@@ -3717,7 +3718,7 @@ void bot_command_levitation(Client *c, const Seperator *sep)
cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id);
break;
}
helper_no_available_bots(c, my_bot);
}
@@ -3787,7 +3788,7 @@ void bot_command_mesmerize(Client *c, const Seperator *sep)
auto target_mob = actionable_targets.Select(c, local_entry->target_type, ENEMY);
if (!target_mob)
continue;
if (spells[local_entry->spell_id].max[EFFECTIDTOINDEX(1)] < target_mob->GetLevel())
continue;
@@ -3850,7 +3851,7 @@ void bot_command_movement_speed(Client *c, const Seperator *sep)
cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id);
break;
}
helper_no_available_bots(c, my_bot);
}
@@ -3859,7 +3860,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep)
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(m_usage, "usage: %s [option] [argument]", sep->arg[0]);
std::string window_title = "Bot Owner Options";
std::string window_text =
"<table>"
@@ -3944,7 +3945,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep)
"<td><c \"#888888\">show current settings</td>"
"</tr>"
"</table>";
c->SendPopupToClient(window_title.c_str(), window_text.c_str());
return;
@@ -3964,7 +3965,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep)
else {
c->SetBotOption(Client::booDeathMarquee, !c->GetBotOption(Client::booDeathMarquee));
}
database.botdb.SaveOwnerOption(c->CharacterID(), Client::booDeathMarquee, c->GetBotOption(Client::booDeathMarquee));
c->Message(m_action, "Bot 'death marquee' is now %s.", (c->GetBotOption(Client::booDeathMarquee) == true ? "enabled" : "disabled"));
@@ -4054,7 +4055,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep)
c->Message(m_action, "Bot 'spawn message' is now %s.", argument.c_str());
}
else if (!owner_option.compare("altcombat")) {
if (RuleB(Bots, AllowOwnerOptionAltCombat)) {
if (!argument.compare("enable")) {
@@ -4130,7 +4131,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep)
c->Message(m_action, "Bot 'monk wu message' is now %s.", (c->GetBotOption(Client::booMonkWuMessage) == true ? "enabled" : "disabled"));
}
else if (!owner_option.compare("current")) {
std::string window_title = "Current Bot Owner Options Settings";
std::string window_text = fmt::format(
"<table>"
@@ -4156,7 +4157,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep)
(c->GetBotOption(Client::booBuffCounter) ? "enabled" : "disabled"),
(c->GetBotOption(Client::booMonkWuMessage) ? "enabled" : "disabled")
);
c->SendPopupToClient(window_title.c_str(), window_text.c_str());
}
else {
@@ -4172,7 +4173,7 @@ void bot_command_pet(Client *c, const Seperator *sep)
subcommand_list.push_back("petremove");
subcommand_list.push_back("petsettype");
/* VS2012 code - end */
/* VS2013 code
const std::list<const char*> subcommand_list = { "petgetlost", "petremove", "petsettype" };
*/
@@ -4205,7 +4206,7 @@ void bot_command_pick_lock(Client *c, const Seperator *sep)
}
Bot* my_bot = sbl.front();
my_bot->InterruptSpell();
Bot::BotGroupSay(my_bot, "Attempting to pick the lock..");
@@ -4310,7 +4311,7 @@ void bot_command_pull(Client *c, const Seperator *sep)
if (bot_iter->GetAppearance() == eaDead || bot_iter->GetBotStance() == EQ::constants::stancePassive) {
continue;
}
switch (bot_iter->GetClass()) {
case ROGUE:
case MONK:
@@ -4385,7 +4386,7 @@ void bot_command_pull(Client *c, const Seperator *sep)
if (bot_puller) {
bot_puller->SetPullFlag();
}
helper_no_available_bots(c, bot_puller);
}
@@ -4452,7 +4453,7 @@ void bot_command_resistance(Client *c, const Seperator *sep)
return true;
if (_l->resist_value[RESISTANCEIDTOINDEX(resistance_type)] == _r->resist_value[RESISTANCEIDTOINDEX(resistance_type)] && spells[_l->spell_id].mana == spells[_r->spell_id].mana && _l->resist_total > _r->resist_total)
return true;
return false;
});
@@ -4480,14 +4481,14 @@ void bot_command_resistance(Client *c, const Seperator *sep)
cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id);
break;
}
helper_no_available_bots(c, my_bot);
}
void bot_command_resurrect(Client *c, const Seperator *sep)
{
// Obscure bot spell code prohibits the aoe portion from working correctly...
bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Resurrect];
if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Resurrect) || helper_command_alias_fail(c, "bot_command_resurrect", sep->arg[0], "resurrect"))
return;
@@ -4516,7 +4517,7 @@ void bot_command_resurrect(Client *c, const Seperator *sep)
// continue;
if (local_entry->aoe)
continue;
auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY);
//if (!target_mob && !local_entry->aoe)
// continue;
@@ -4573,14 +4574,14 @@ void bot_command_rune(Client *c, const Seperator *sep)
cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id);
break;
}
helper_no_available_bots(c, my_bot);
}
void bot_command_send_home(Client *c, const Seperator *sep)
{
// Obscure bot spell code prohibits the aoe portion from working correctly...
bcst_list* local_list = &bot_command_spells[BCEnum::SpT_SendHome];
if (helper_spell_list_fail(c, local_list, BCEnum::SpT_SendHome) || helper_command_alias_fail(c, "bot_command_send_home", sep->arg[0], "sendhome"))
return;
@@ -4607,7 +4608,7 @@ void bot_command_send_home(Client *c, const Seperator *sep)
continue;
if (local_entry->group != group)
continue;
auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY);
if (!target_mob)
continue;
@@ -4668,7 +4669,7 @@ void bot_command_size(Client *c, const Seperator *sep)
cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id);
break;
}
helper_no_available_bots(c, my_bot);
}
@@ -4679,7 +4680,7 @@ void bot_command_summon_corpse(Client *c, const Seperator *sep)
// temp
c->Message(m_fail, "This command is currently unavailable...");
return;
bcst_list* local_list = &bot_command_spells[BCEnum::SpT_SummonCorpse];
if (helper_spell_list_fail(c, local_list, BCEnum::SpT_SummonCorpse) || helper_command_alias_fail(c, "bot_command_summon_corpse", sep->arg[0], "summoncorpse"))
return;
@@ -4698,7 +4699,7 @@ void bot_command_summon_corpse(Client *c, const Seperator *sep)
auto local_entry = list_iter;
if (helper_spell_check_fail(local_entry))
continue;
auto target_mob = ActionableTarget::AsSingle_ByPlayer(c);
if (!target_mob)
continue;
@@ -4711,7 +4712,7 @@ void bot_command_summon_corpse(Client *c, const Seperator *sep)
continue;
cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id);
break;
}
@@ -4771,12 +4772,12 @@ void bot_command_taunt(Client *c, const Seperator *sep)
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[(ab_arg + 1)]) == ActionableBots::ABT_None)
return;
sbl.remove(nullptr);
int taunting_count = 0;
for (auto bot_iter : sbl) {
if (!bot_iter->GetSkill(EQ::skills::SkillTaunt))
continue;
if (toggle_taunt)
bot_iter->SetTaunting(!bot_iter->IsTaunting());
else
@@ -4814,10 +4815,10 @@ void bot_command_track(Client *c, const Seperator *sep)
std::list<Bot*> sbl;
MyBots::PopulateSBL_BySpawnedBots(c, sbl);
uint16 class_mask = (PLAYER_CLASS_RANGER_BIT | PLAYER_CLASS_DRUID_BIT | PLAYER_CLASS_BARD_BIT);
ActionableBots::Filter_ByClasses(c, sbl, class_mask);
Bot* my_bot = ActionableBots::AsSpawned_ByMinLevelAndClass(c, sbl, 1, RANGER);
if (tracking_scope.empty()) {
if (!my_bot)
@@ -4903,7 +4904,7 @@ void bot_command_water_breathing(Client *c, const Seperator *sep)
cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id);
break;
}
helper_no_available_bots(c, my_bot);
}
@@ -4926,14 +4927,14 @@ void bot_subcommand_bot_appearance(Client *c, const Seperator *sep)
subcommand_list.push_back("bottattoo");
subcommand_list.push_back("botwoad");
/* VS2012 code - end */
/* VS2013 code
const std::list<const char*> subcommand_list = {
"botbeardcolor", "botbeardstyle", "botdetails", "boteyes", "botface",
"bothaircolor", "bothairstyle", "botheritage", "bottattoo", "botwoad"
};
*/
if (helper_command_alias_fail(c, "bot_subcommand_bot_appearance", sep->arg[0], "botappearance"))
return;
@@ -5102,7 +5103,7 @@ void bot_subcommand_bot_clone(Client *c, const Seperator *sep)
if (!database.botdb.CreateCloneBotInventory(c->CharacterID(), my_bot->GetBotID(), clone_id))
c->Message(m_fail, "%s for clone '%s'", BotDatabase::fail::CreateCloneBotInventory(), bot_name.c_str());
c->Message(m_action, "Bot '%s' was successfully cloned to bot '%s'", my_bot->GetCleanName(), bot_name.c_str());
}
@@ -5257,7 +5258,7 @@ void bot_subcommand_bot_delete(Client *c, const Seperator *sep)
void bot_subcommand_bot_details(Client *c, const Seperator *sep)
{
// TODO: Trouble-shoot model update issue
if (helper_command_alias_fail(c, "bot_subcommand_bot_details", sep->arg[0], "botdetails"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
@@ -5296,7 +5297,7 @@ void bot_subcommand_bot_details(Client *c, const Seperator *sep)
void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep)
{
// TODO: Trouble-shoot model update issue
const std::string msg_matslot = StringFormat("mat_slot: %c(All), %i(Head), %i(Chest), %i(Arms), %i(Wrists), %i(Hands), %i(Legs), %i(Feet)",
'*', EQ::textures::armorHead, EQ::textures::armorChest, EQ::textures::armorArms, EQ::textures::armorWrist, EQ::textures::armorHands, EQ::textures::armorLegs, EQ::textures::armorFeet);
@@ -5377,7 +5378,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep)
void bot_subcommand_bot_eyes(Client *c, const Seperator *sep)
{
// TODO: Trouble-shoot model update issue
// not sure if left/right bias is allowed in pc-type entities (something is keeping them from being different)
if (helper_command_alias_fail(c, "bot_subcommand_bot_eyes", sep->arg[0], "boteyes"))
return;
@@ -5611,7 +5612,7 @@ void bot_subcommand_bot_hairstyle(Client *c, const Seperator *sep)
void bot_subcommand_bot_heritage(Client *c, const Seperator *sep)
{
// TODO: Trouble-shoot model update issue
if (helper_command_alias_fail(c, "bot_subcommand_bot_heritage", sep->arg[0], "botheritage"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
@@ -5640,7 +5641,7 @@ void bot_subcommand_bot_heritage(Client *c, const Seperator *sep)
fail_type = BCEnum::AFT_Value;
else
my_bot->SetDrakkinHeritage(uvalue);
if (helper_bot_appearance_fail(c, my_bot, fail_type, "heritage"))
return;
@@ -5856,7 +5857,7 @@ void bot_subcommand_bot_out_of_combat(Client *c, const Seperator *sep)
bot_iter->SetAltOutOfCombatBehavior(!bot_iter->GetAltOutOfCombatBehavior());
else
bot_iter->SetAltOutOfCombatBehavior(behavior_state);
helper_bot_out_of_combat(c, bot_iter);
}
}
@@ -6069,7 +6070,7 @@ void bot_subcommand_bot_spawn(Client *c, const Seperator *sep)
c->Message(m_fail, "You can't spawn bots while you are engaged.");
return;
}
//if (c->IsEngaged()) {
// c->Message(m_fail, "You can't spawn bots while you are engaged.");
// return;
@@ -6268,7 +6269,7 @@ void bot_subcommand_bot_summon(Client *c, const Seperator *sep)
void bot_subcommand_bot_tattoo(Client *c, const Seperator *sep)
{
// TODO: Trouble-shoot model update issue
if (helper_command_alias_fail(c, "bot_subcommand_bot_tattoo", sep->arg[0], "bottattoo"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
@@ -6336,7 +6337,7 @@ void bot_subcommand_bot_toggle_archer(Client *c, const Seperator *sep)
for (auto bot_iter : sbl) {
if (!bot_iter)
continue;
if (toggle_archer)
bot_iter->SetBotArcher(!bot_iter->IsBotArcher());
else
@@ -6925,7 +6926,7 @@ void bot_subcommand_botgroup_load(Client *c, const Seperator *sep)
safe_delete(botgroup_leader);
return;
}
Group* group_inst = new Group(botgroup_leader);
entity_list.AddGroup(group_inst);
@@ -7052,7 +7053,7 @@ void bot_subcommand_circle(Client *c, const Seperator *sep)
cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id);
break;
}
helper_no_available_bots(c, my_bot);
}
@@ -7536,7 +7537,7 @@ void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep)
sep->arg[0], CASTING_CYCLE_DEFAULT_INTERVAL_S, CASTING_CYCLE_MINIMUM_INTERVAL_S, CASTING_CYCLE_MAXIMUM_INTERVAL_S);
return;
}
std::string interval_arg;
std::string fast_heals_arg;
std::string adaptive_targeting_arg;
@@ -7594,10 +7595,10 @@ void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep)
hr_fast_heals = true;
hr_interval_s = atoi(interval_arg.c_str());
}
if (hr_interval_s < CASTING_CYCLE_MINIMUM_INTERVAL_S || hr_interval_s > CASTING_CYCLE_MAXIMUM_INTERVAL_S)
hr_interval_s = CASTING_CYCLE_DEFAULT_INTERVAL_S;
hr_interval_s *= 1000; // convert to milliseconds for Bot/HealRotation constructor
if (!creator_member->CreateHealRotation(hr_interval_s, hr_fast_heals, hr_adaptive_targeting, hr_casting_override)) {
@@ -7613,12 +7614,12 @@ void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep)
if (!database.botdb.LoadHealRotation(creator_member, member_list, target_list, load_flag, member_fail, target_fail))
c->Message(m_fail, "%s", BotDatabase::fail::LoadHealRotation());
if (!load_flag) {
c->Message(m_action, "Successfully added %s as a current member to a new Heal Rotation", creator_member->GetCleanName());
return;
}
if (!member_fail) {
MyBots::PopulateSBL_BySpawnedBots(c, sbl);
for (auto member_iter : member_list) {
@@ -7663,7 +7664,7 @@ void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep)
else {
c->Message(m_fail, "%s", BotDatabase::fail::LoadHealRotationTargets());
}
c->Message(m_action, "Successfully loaded %s's Heal Rotation", creator_member->GetCleanName());
}
@@ -8198,7 +8199,7 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep)
c->Message(m_message, "I need something for my %s (slot %i)", EQ::invslot::GetInvPossessionsSlotName(i), i);
continue;
}
item = inst->GetItem();
if ((i == EQ::invslot::slotPrimary) && item->IsType2HWeapon()) {
is2Hweapon = true;
@@ -8272,7 +8273,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep)
c->MessageString(Chat::White, PICK_LORE);
return;
}
std::string error_message;
if (itm) {
c->PushItemOnCursor(*itminst, true);
@@ -8517,7 +8518,7 @@ void bot_subcommand_pet_set_type(Client *c, const Seperator *sep)
c->Message(m_fail, "You have no spawned Magician bots capable of using this pet type: '%s'", pet_arg.c_str());
return;
}
uint16 reclaim_energy_id = 331;
for (auto bot_iter : sbl) {
if (!bot_iter)
@@ -8588,7 +8589,7 @@ void bot_subcommand_portal(Client *c, const Seperator *sep)
cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id);
break;
}
helper_no_available_bots(c, my_bot);
}
+34 -34
View File
@@ -24,6 +24,7 @@
#include "../common/eqemu_logsys.h"
#include "zonedb.h"
#include "zone_store.h"
#include "bot.h"
#include "client.h"
@@ -192,7 +193,7 @@ bool BotDatabase::QueryBotCount(const uint32 owner_id, uint32& bot_count)
return false;
if (!results.RowCount())
return true;
auto row = results.begin();
bot_count = atoi(row[0]);
@@ -314,7 +315,7 @@ bool BotDatabase::LoadBotID(const uint32 owner_id, const std::string& bot_name,
return false;
if (!results.RowCount())
return true;
auto row = results.begin();
bot_id = atoi(row[0]);
@@ -451,7 +452,7 @@ bool BotDatabase::SaveNewBot(Bot* bot_inst, uint32& bot_id)
{
if (!bot_inst)
return false;
query = StringFormat(
"INSERT INTO `bot_data` ("
" `owner_id`,"
@@ -596,7 +597,7 @@ bool BotDatabase::SaveBot(Bot* bot_inst)
{
if (!bot_inst)
return false;
query = StringFormat(
"UPDATE `bot_data`"
" SET"
@@ -1014,7 +1015,7 @@ bool BotDatabase::LoadTimers(Bot* bot_inst)
if (timer_id >= 0 && timer_id < MaxTimer && timer_value < (Timer::GetCurrentTime() + max_value))
bot_timers[timer_id] = timer_value;
}
return true;
}
@@ -1127,7 +1128,7 @@ bool BotDatabase::QueryInventoryCount(const uint32 bot_id, uint32& item_count)
{
if (!bot_id)
return false;
query = StringFormat("SELECT COUNT(`inventories_index`) FROM `bot_inventories` WHERE `bot_id` = '%u'", bot_id);
auto results = database.QueryDatabase(query);
if (!results.Success())
@@ -1173,7 +1174,7 @@ bool BotDatabase::LoadItems(const uint32 bot_id, EQ::InventoryProfile& inventory
return false;
if (!results.RowCount())
return true;
for (auto row = results.begin(); row != results.end(); ++row) {
int16 slot_id = atoi(row[0]);
if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END)
@@ -1281,7 +1282,7 @@ bool BotDatabase::LoadItemBySlot(const uint32 bot_id, const uint32 slot_id, uint
{
if (!bot_id || slot_id > EQ::invslot::EQUIPMENT_END)
return false;
query = StringFormat("SELECT `item_id` FROM `bot_inventories` WHERE `bot_id` = '%i' AND `slot_id` = '%i' LIMIT 1", bot_id, slot_id);
auto results = database.QueryDatabase(query);
if (!results.Success())
@@ -1305,11 +1306,10 @@ bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const EQ::
if (!item_inst || !item_inst->GetID())
return true;
uint32 augment_id[EQ::invaug::SOCKET_COUNT] = { 0, 0, 0, 0, 0, 0 };
for (int augment_iter = EQ::invaug::SOCKET_BEGIN; augment_iter <= EQ::invaug::SOCKET_END; ++augment_iter)
augment_id[augment_iter] = item_inst->GetAugmentItemID(augment_iter);
uint16 item_charges = 0;
if (item_inst->GetCharges() >= 0)
item_charges = item_inst->GetCharges();
@@ -1400,7 +1400,7 @@ bool BotDatabase::LoadEquipmentColor(const uint32 bot_id, const uint8 material_s
int16 slot_id = EQ::InventoryProfile::CalcSlotFromMaterial(material_slot_id);
if (slot_id == INVALID_INDEX)
return false;
query = StringFormat("SELECT `inst_color` FROM `bot_inventories` WHERE `bot_id` = '%u' AND `slot_id` = '%u' LIMIT 1", bot_id, slot_id);
auto results = database.QueryDatabase(query);
if (!results.Success())
@@ -1451,7 +1451,7 @@ bool BotDatabase::LoadPetIndex(const uint32 bot_id, uint32& pet_index)
{
if (!bot_id)
return false;
query = StringFormat("SELECT `pets_index` FROM `bot_pets` WHERE `bot_id` = '%u' LIMIT 1", bot_id);
auto results = database.QueryDatabase(query);
if (!results.Success())
@@ -1461,7 +1461,7 @@ bool BotDatabase::LoadPetIndex(const uint32 bot_id, uint32& pet_index)
auto row = results.begin();
pet_index = atoi(row[0]);
return true;
}
@@ -1479,7 +1479,7 @@ bool BotDatabase::LoadPetSpellID(const uint32 bot_id, uint32& pet_spell_id)
auto row = results.begin();
pet_spell_id = atoi(row[0]);
return true;
}
@@ -1506,7 +1506,7 @@ bool BotDatabase::LoadPetStats(const uint32 bot_id, std::string& pet_name, uint3
pet_name = row[1];
pet_mana = atoi(row[2]);
pet_hp = atoi(row[3]);
return true;
}
@@ -1514,7 +1514,7 @@ bool BotDatabase::SavePetStats(const uint32 bot_id, const std::string& pet_name,
{
if (!bot_id || pet_name.empty() || !pet_spell_id || pet_spell_id > SPDAT_RECORDS)
return false;
if (!DeletePetItems(bot_id))
return false;
if (!DeletePetBuffs(bot_id))
@@ -1607,14 +1607,14 @@ bool BotDatabase::LoadPetBuffs(const uint32 bot_id, SpellBuff_Struct* pet_buffs)
++buff_index;
}
return true;
}
bool BotDatabase::SavePetBuffs(const uint32 bot_id, const SpellBuff_Struct* pet_buffs, bool delete_flag)
{
// Only use 'delete_flag' if not invoked after a botdb.SavePetStats() call
if (!bot_id || !pet_buffs)
return false;
@@ -1701,14 +1701,14 @@ bool BotDatabase::LoadPetItems(const uint32 bot_id, uint32* pet_items)
pet_items[item_index] = atoi(row[0]);
++item_index;
}
return true;
}
bool BotDatabase::SavePetItems(const uint32 bot_id, const uint32* pet_items, bool delete_flag)
{
// Only use 'delete_flag' if not invoked after a botdb.SavePetStats() call
if (!bot_id || !pet_items)
return false;
@@ -1777,7 +1777,7 @@ bool BotDatabase::LoadInspectMessage(const uint32 bot_id, InspectMessage_Struct&
return true;
memcpy(inspect_message.text, bot_message.c_str(), bot_message.size());
return true;
}
@@ -1785,7 +1785,7 @@ bool BotDatabase::SaveInspectMessage(const uint32 bot_id, const InspectMessage_S
{
if (!bot_id)
return false;
if (!DeleteInspectMessage(bot_id))
return false;
@@ -1825,7 +1825,7 @@ bool BotDatabase::SaveAllInspectMessages(const uint32 owner_id, const InspectMes
if (!DeleteAllInspectMessages(owner_id))
return false;
std::string bot_message = inspect_message.text;
if (bot_message.size() > 255)
bot_message = bot_message.substr(0, 255);
@@ -1907,7 +1907,7 @@ bool BotDatabase::SaveHelmAppearance(const uint32 owner_id, const uint32 bot_id,
{
if (!owner_id || !bot_id)
return false;
query = StringFormat(
"UPDATE `bot_data`"
" SET `show_helm` = '%u'"
@@ -2025,7 +2025,7 @@ bool BotDatabase::CreateCloneBot(const uint32 owner_id, const uint32 bot_id, con
{
if (!owner_id || !bot_id || clone_name.empty())
return false;
query = StringFormat(
"INSERT INTO `bot_data`"
" ("
@@ -2198,7 +2198,7 @@ bool BotDatabase::CreateCloneBotInventory(const uint32 owner_id, const uint32 bo
DeleteItems(clone_id);
return false;
}
return true;
}
@@ -2237,7 +2237,7 @@ bool BotDatabase::LoadOwnerOptions(Client *owner)
}
for (auto row : results) {
owner->SetBotOption(static_cast<Client::BotOwnerOption>(atoul(row[0])), (atoul(row[1]) != 0));
}
@@ -2369,7 +2369,7 @@ bool BotDatabase::LoadBotGroupIDByLeaderID(const uint32 leader_id, uint32& botgr
auto row = results.begin();
botgroup_id = atoi(row[0]);
return true;
}
@@ -2387,7 +2387,7 @@ bool BotDatabase::LoadBotGroupIDByMemberID(const uint32 member_id, uint32& botgr
auto row = results.begin();
botgroup_id = atoi(row[0]);
return true;
}
@@ -2405,7 +2405,7 @@ bool BotDatabase::LoadLeaderIDByBotGroupName(const std::string& group_name, uint
auto row = results.begin();
leader_id = atoi(row[0]);
return true;
}
@@ -2423,7 +2423,7 @@ bool BotDatabase::LoadLeaderIDByBotGroupID(const uint32 group_id, uint32& leader
auto row = results.begin();
leader_id = atoi(row[0]);
return true;
}
@@ -2441,7 +2441,7 @@ bool BotDatabase::LoadBotGroupNameByBotGroupID(const uint32 group_id, std::strin
auto row = results.begin();
botgroup_name = row[0];
return true;
}
@@ -2459,7 +2459,7 @@ bool BotDatabase::LoadBotGroupNameByLeaderID(const uint32 leader_id, std::string
auto row = results.begin();
botgroup_name = row[0];
return true;
}
@@ -2603,7 +2603,7 @@ bool BotDatabase::LoadBotGroup(const std::string& group_name, std::map<uint32, s
for (auto row = results.begin(); row != results.end(); ++row)
member_list[botgroup_id].push_back(atoi(row[0]));
return true;
}
+44 -30
View File
@@ -43,6 +43,7 @@ extern volatile bool RunLoops;
#include "position.h"
#include "worldserver.h"
#include "zonedb.h"
#include "zone_store.h"
#include "petitions.h"
#include "command.h"
#include "water_map.h"
@@ -2094,7 +2095,7 @@ void Client::ReadBook(BookRequest_Struct *book) {
return;
}
std::string booktxt2 = database.GetBook(txtfile, &book_language);
std::string booktxt2 = content_db.GetBook(txtfile, &book_language);
int length = booktxt2.length();
if (booktxt2[0] != '\0') {
@@ -4005,7 +4006,7 @@ void Client::SendOPTranslocateConfirm(Mob *Caster, uint16 SpellID) {
PendingTranslocateData.heading = m_pp.binds[0].heading;
}
else {
PendingTranslocateData.zone_id = ts->ZoneID = database.GetZoneID(Spell.teleport_zone);
PendingTranslocateData.zone_id = ts->ZoneID = ZoneID(Spell.teleport_zone);
PendingTranslocateData.instance_id = 0;
PendingTranslocateData.y = ts->y = Spell.base[0];
PendingTranslocateData.x = ts->x = Spell.base[1];
@@ -5287,7 +5288,7 @@ void Client::SetStartZone(uint32 zoneid, float x, float y, float z)
}
// check to make sure the zone is valid
const char *target_zone_name = database.GetZoneName(zoneid);
const char *target_zone_name = ZoneName(zoneid);
if(target_zone_name == nullptr)
return;
@@ -5296,8 +5297,9 @@ void Client::SetStartZone(uint32 zoneid, float x, float y, float z)
m_pp.binds[4].instance_id = zone->GetInstanceID();
}
if (x == 0 && y == 0 && z ==0)
database.GetSafePoints(m_pp.binds[4].zoneId, 0, &m_pp.binds[4].x, &m_pp.binds[4].y, &m_pp.binds[4].z);
if (x == 0 && y == 0 && z == 0) {
content_db.GetSafePoints(ZoneName(m_pp.binds[4].zoneId), 0, &m_pp.binds[4].x, &m_pp.binds[4].y, &m_pp.binds[4].z);
}
else {
m_pp.binds[4].x = x;
m_pp.binds[4].y = y;
@@ -6122,16 +6124,16 @@ void Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z, uint8 coun
void Client::SendZonePoints()
{
int count = 0;
LinkedListIterator<ZonePoint*> iterator(zone->zone_point_list);
int count = 0;
LinkedListIterator<ZonePoint *> iterator(zone->zone_point_list);
iterator.Reset();
while(iterator.MoreElements())
{
ZonePoint* data = iterator.GetData();
if(ClientVersionBit() & data->client_version_mask)
{
while (iterator.MoreElements()) {
ZonePoint *data = iterator.GetData();
if (ClientVersionBit() & data->client_version_mask) {
count++;
}
iterator.Advance();
}
@@ -6145,6 +6147,17 @@ void Client::SendZonePoints()
while(iterator.MoreElements())
{
ZonePoint* data = iterator.GetData();
LogZonePoints(
"Sending zone point to client [{}] mask [{}] x [{}] y [{}] z [{}] number [{}]",
GetCleanName(),
ClientVersionBit() & data->client_version_mask ? "true" : "false",
data->x,
data->y,
data->z,
data->number
);
if(ClientVersionBit() & data->client_version_mask)
{
zp->zpe[i].iterator = data->number;
@@ -6158,6 +6171,7 @@ void Client::SendZonePoints()
}
iterator.Advance();
}
FastQueuePacket(&outapp);
}
@@ -6206,21 +6220,21 @@ void Client::NPCSpawn(NPC *target_npc, const char *identifier, uint32 extra)
if (id == "create") {
// extra tries to create the npc_type ID within the range for the current zone (zone_id * 1000)
database.NPCSpawnDB(0, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC(), extra);
content_db.NPCSpawnDB(0, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC(), extra);
}
else if (id == "add") {
// extra sets the respawn timer for add
database.NPCSpawnDB(1, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC(), extra);
content_db.NPCSpawnDB(1, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC(), extra);
}
else if (id == "update") {
database.NPCSpawnDB(2, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC());
content_db.NPCSpawnDB(2, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC());
}
else if (id == "remove") {
database.NPCSpawnDB(3, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC());
content_db.NPCSpawnDB(3, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC());
target_npc->Depop(false);
}
else if (id == "delete") {
database.NPCSpawnDB(4, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC());
content_db.NPCSpawnDB(4, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC());
target_npc->Depop(false);
}
else {
@@ -6324,7 +6338,7 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid
NPCType *made_npc = nullptr;
const NPCType *npc_type = database.LoadNPCTypesData(pet.npc_id);
const NPCType *npc_type = content_db.LoadNPCTypesData(pet.npc_id);
if(npc_type == nullptr) {
LogError("Unknown npc type for doppelganger spell id: [{}]", spell_id);
Message(0,"Unable to find pet!");
@@ -6849,7 +6863,7 @@ void Client::SendStatsWindow(Client* client, bool use_window)
for (auto iter = item_faction_bonuses.begin(); iter != item_faction_bonuses.end(); ++iter) {
memset(&faction_buf, 0, sizeof(faction_buf));
if(!database.GetFactionName((int32)((*iter).first), faction_buf, sizeof(faction_buf)))
if(!content_db.GetFactionName((int32)((*iter).first), faction_buf, sizeof(faction_buf)))
strcpy(faction_buf, "Not in DB");
if((*iter).second > 0) {
@@ -7816,7 +7830,7 @@ FACTION_VALUE Client::GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 p_ra
if(pFaction > 0)
{
//Get the faction data from the database
if(database.GetFactionData(&fmods, p_class, p_race, p_deity, pFaction))
if(content_db.GetFactionData(&fmods, p_class, p_race, p_deity, pFaction))
{
//Get the players current faction with pFaction
tmpFactionValue = GetCharacterFactionLevel(pFaction);
@@ -7851,10 +7865,11 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui
int32 current_value;
// Get the npc faction list
if (!database.GetNPCFactionList(npc_id, faction_id, npc_value, temp))
if (!content_db.GetNPCFactionList(npc_id, faction_id, npc_value, temp)) {
return;
for (int i = 0; i < MAX_NPC_FACTIONS; i++)
{
}
for (int i = 0; i < MAX_NPC_FACTIONS; i++) {
int32 faction_before_hit;
int32 faction_to_use_for_messaging;
FactionMods fm;
@@ -7867,8 +7882,7 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui
// Find out starting faction for this faction
// It needs to be used to adj max and min personal
// The range is still the same, 1200-3000(4200), but adjusted for base
database.GetFactionData(&fm, GetClass(), GetFactionRace(), GetDeity(),
faction_id[i]);
content_db.GetFactionData(&fm, GetClass(), GetFactionRace(), GetDeity(), faction_id[i]);
if (quest)
{
@@ -7917,7 +7931,7 @@ void Client::SetFactionLevel2(uint32 char_id, int32 faction_id, uint8 char_class
// Find out starting faction for this faction
// It needs to be used to adj max and min personal
// The range is still the same, 1200-3000(4200), but adjusted for base
database.GetFactionData(&fm, GetClass(), GetFactionRace(), GetDeity(),
content_db.GetFactionData(&fm, GetClass(), GetFactionRace(), GetDeity(),
faction_id);
// Adjust the amount you can go up or down so the resulting range
@@ -8018,7 +8032,7 @@ return;
int32 Client::GetModCharacterFactionLevel(int32 faction_id) {
int32 Modded = GetCharacterFactionLevel(faction_id);
FactionMods fm;
if (database.GetFactionData(&fm, GetClass(), GetFactionRace(), GetDeity(), faction_id))
if (content_db.GetFactionData(&fm, GetClass(), GetFactionRace(), GetDeity(), faction_id))
{
Modded += fm.base + fm.class_mod + fm.race_mod + fm.deity_mod;
@@ -8039,7 +8053,7 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction)
// If a faction is involved, get the data.
if (primaryfaction > 0) {
if (database.GetFactionData(&fmod, GetClass(), GetFactionRace(), GetDeity(), primaryfaction)) {
if (content_db.GetFactionData(&fmod, GetClass(), GetFactionRace(), GetDeity(), primaryfaction)) {
tmpFactionValue = GetCharacterFactionLevel(primaryfaction);
lowestvalue = std::min(std::min(tmpFactionValue, fmod.deity_mod),
std::min(fmod.class_mod, fmod.race_mod));
@@ -8124,7 +8138,7 @@ void Client::SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_
faction_value = faction_before_hit;
// default to Faction# if we couldn't get the name from the ID
if (database.GetFactionName(faction_id, name, sizeof(name)) == false)
if (content_db.GetFactionName(faction_id, name, sizeof(name)) == false)
snprintf(name, sizeof(name), "Faction%i", faction_id);
if (tmpvalue == 0 || temp == 1 || temp == 2)
@@ -9297,7 +9311,7 @@ void Client::SetBotOption(BotOwnerOption boo, bool flag) {
void Client::SendToGuildHall()
{
std::string zone_short_name = "guildhall";
uint32 zone_id = database.GetZoneID(zone_short_name.c_str());
uint32 zone_id = ZoneID(zone_short_name.c_str());
if (zone_id == 0) {
return;
}
+3 -2
View File
@@ -58,6 +58,7 @@ namespace EQ
#include "questmgr.h"
#include "zone.h"
#include "zonedb.h"
#include "zone_store.h"
#ifdef _WINDOWS
// since windows defines these within windef.h (which windows.h include)
@@ -290,7 +291,7 @@ public:
const char *message9 = nullptr);
void Tell_StringID(uint32 string_id, const char *who, const char *message);
void SendColoredText(uint32 color, std::string message);
void SendBazaarResults(uint32 trader_id,uint32 class_,uint32 race,uint32 stat,uint32 slot,uint32 type,char name[64],uint32 minprice,uint32 maxprice);
void SendBazaarResults(uint32 trader_id, uint32 in_class, uint32 in_race, uint32 item_stat, uint32 item_slot, uint32 item_type, char item_name[64], uint32 min_price, uint32 max_price);
void SendTraderItem(uint32 item_id,uint16 quantity);
uint16 FindTraderItem(int32 SerialNumber,uint16 Quantity);
uint32 FindTraderItemSerialNumber(int32 ItemID);
@@ -753,7 +754,7 @@ public:
inline uint16 MaxSkill(EQ::skills::SkillType skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); }
uint8 SkillTrainLevel(EQ::skills::SkillType skillid, uint16 class_);
void TradeskillSearchResults(const std::string &query, unsigned long objtype, unsigned long someid);
void SendTradeskillSearchResults(const std::string &query, unsigned long objtype, unsigned long someid);
void SendTradeskillDetails(uint32 recipe_id);
bool TradeskillExecute(DBTradeskillRecipe_Struct *spec);
void CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float skillup_modifier, uint16 success_modifier, EQ::skills::SkillType tradeskill);
+143 -72
View File
@@ -61,6 +61,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "worldserver.h"
#include "zone.h"
#include "mob_movement_manager.h"
#include "../common/repositories/criteria/content_filter_criteria.h"
#ifdef BOTS
#include "bot.h"
@@ -789,7 +790,7 @@ void Client::CompleteConnect()
//enforce some rules..
if (!CanBeInZone()) {
LogDebug("[CLIENT] Kicking char from zone, not allowed here");
GoToSafeCoords(database.GetZoneID("arena"), 0);
GoToSafeCoords(ZoneID("arena"), 0);
return;
}
@@ -6418,14 +6419,14 @@ void Client::Handle_OP_GMZoneRequest(const EQApplicationPacket *app)
uint16 zid = gmzr->zone_id;
if (gmzr->zone_id == 0)
zid = zonesummon_id;
const char * zname = database.GetZoneName(zid);
const char * zname = ZoneName(zid);
if (zname == nullptr)
tarzone[0] = 0;
else
strcpy(tarzone, zname);
// this both loads the safe points and does a sanity check on zone name
if (!database.GetSafePoints(tarzone, 0, &tarx, &tary, &tarz, &minstatus, &minlevel)) {
if (!content_db.GetSafePoints(tarzone, 0, &tarx, &tary, &tarz, &minstatus, &minlevel)) {
tarzone[0] = 0;
}
@@ -11796,7 +11797,7 @@ void Client::Handle_OP_RecipesFavorite(const EQApplicationPacket *app)
{
if (app->size != sizeof(TradeskillFavorites_Struct)) {
LogError("Invalid size for TradeskillFavorites_Struct: Expected: [{}], Got: [{}]",
sizeof(TradeskillFavorites_Struct), app->size);
sizeof(TradeskillFavorites_Struct), app->size);
return;
}
@@ -11846,90 +11847,155 @@ void Client::Handle_OP_RecipesFavorite(const EQApplicationPacket *app)
if (first) //no favorites....
return;
const std::string query = StringFormat("SELECT tr.id, tr.name, tr.trivial, "
"SUM(tre.componentcount), crl.madecount,tr.tradeskill "
"FROM tradeskill_recipe AS tr "
"LEFT JOIN tradeskill_recipe_entries AS tre ON tr.id=tre.recipe_id "
"LEFT JOIN (SELECT recipe_id, madecount "
"FROM char_recipe_list "
"WHERE char_id = %u) AS crl ON tr.id=crl.recipe_id "
"WHERE tr.enabled <> 0 AND tr.id IN (%s) "
"AND tr.must_learn & 0x20 <> 0x20 AND "
"((tr.must_learn & 0x3 <> 0 AND crl.madecount IS NOT NULL) "
"OR (tr.must_learn & 0x3 = 0)) "
"GROUP BY tr.id "
"HAVING sum(if(tre.item_id %s AND tre.iscontainer > 0,1,0)) > 0 AND SUM(tre.componentcount) <= %u "
"LIMIT 100 ", CharacterID(), favoriteIDs.c_str(), containers.c_str(), combineObjectSlots);
// TODO: Clean this up
const std::string query = StringFormat(
SQL (
SELECT
tr.id,
tr.name,
tr.trivial,
SUM(tre.componentcount),
tr.tradeskill
FROM
tradeskill_recipe AS tr
LEFT JOIN tradeskill_recipe_entries AS tre ON tr.id = tre.recipe_id
WHERE
tr.enabled <> 0
AND tr.id IN (%s)
AND tr.must_learn & 0x20 <> 0x20
AND (
(
tr.must_learn & 0x3 <> 0
)
OR (tr.must_learn & 0x3 = 0)
)
%s
GROUP BY
tr.id
HAVING
sum(
if(
tre.item_id %s
AND tre.iscontainer > 0,
1,
0
)
) > 0
AND SUM(tre.componentcount) <= %u
TradeskillSearchResults(query, tsf->object_type, tsf->some_id);
return;
LIMIT
100
),
favoriteIDs.c_str(),
ContentFilterCriteria::apply().c_str(),
containers.c_str(),
combineObjectSlots
);
SendTradeskillSearchResults(query, tsf->object_type, tsf->some_id);
}
void Client::Handle_OP_RecipesSearch(const EQApplicationPacket *app)
{
if (app->size != sizeof(RecipesSearch_Struct)) {
LogError("Invalid size for RecipesSearch_Struct: Expected: [{}], Got: [{}]",
sizeof(RecipesSearch_Struct), app->size);
LogError(
"Invalid size for RecipesSearch_Struct: Expected: [{}], Got: [{}]",
sizeof(RecipesSearch_Struct),
app->size
);
return;
}
RecipesSearch_Struct* rss = (RecipesSearch_Struct*)app->pBuffer;
rss->query[55] = '\0'; //just to be sure.
auto* p_recipes_search_struct = (RecipesSearch_Struct*)app->pBuffer;
p_recipes_search_struct->query[55] = '\0'; //just to be sure.
LogTradeskills(
"[Handle_OP_RecipesSearch] Requested search recipes for object_type [{}] some_id [{}]",
p_recipes_search_struct->object_type,
p_recipes_search_struct->some_id
);
LogDebug("Requested search recipes for: [{}] - [{}]\n", rss->object_type, rss->some_id);
// make where clause segment for container(s)
char containers[30];
uint32 combineObjectSlots;
if (rss->some_id == 0) {
char containers_where_clause[30];
uint32 combine_object_slots;
if (p_recipes_search_struct->some_id == 0) {
// world combiner so no item number
snprintf(containers, 29, "= %u", rss->object_type);
combineObjectSlots = 10;
snprintf(containers_where_clause, 29, "= %u", p_recipes_search_struct->object_type);
combine_object_slots = 10;
}
else {
// container in inventory
snprintf(containers, 29, "in (%u,%u)", rss->object_type, rss->some_id);
auto item = database.GetItem(rss->some_id);
if (!item)
{
LogError("Invalid container ID: [{}]. GetItem returned null. Defaulting to BagSlots = 10.\n", rss->some_id);
combineObjectSlots = 10;
snprintf(containers_where_clause, 29, "in (%u,%u)", p_recipes_search_struct->object_type, p_recipes_search_struct->some_id);
auto item = database.GetItem(p_recipes_search_struct->some_id);
if (!item) {
LogError(
"Invalid container ID: [{}]. GetItem returned null. Defaulting to BagSlots = 10.",
p_recipes_search_struct->some_id
);
combine_object_slots = 10;
}
else
{
combineObjectSlots = item->BagSlots;
else {
combine_object_slots = item->BagSlots;
}
}
std::string searchClause;
//omit the rlike clause if query is empty
if (rss->query[0] != 0) {
std::string search_clause;
if (p_recipes_search_struct->query[0] != 0) {
char buf[120]; //larger than 2X rss->query
database.DoEscapeString(buf, rss->query, strlen(rss->query));
searchClause = StringFormat("name rlike '%s' AND", buf);
database.DoEscapeString(buf, p_recipes_search_struct->query, strlen(p_recipes_search_struct->query));
search_clause = StringFormat("name rlike '%s' AND", buf);
}
//arbitrary limit of 200 recipes, makes sense to me.
const std::string query = StringFormat("SELECT tr.id, tr.name, tr.trivial, "
"SUM(tre.componentcount), crl.madecount,tr.tradeskill "
"FROM tradeskill_recipe AS tr "
"LEFT JOIN tradeskill_recipe_entries AS tre ON tr.id = tre.recipe_id "
"LEFT JOIN (SELECT recipe_id, madecount "
"FROM char_recipe_list WHERE char_id = %u) AS crl ON tr.id=crl.recipe_id "
"WHERE %s tr.trivial >= %u AND tr.trivial <= %u AND tr.enabled <> 0 "
"AND tr.must_learn & 0x20 <> 0x20 "
"AND ((tr.must_learn & 0x3 <> 0 "
"AND crl.madecount IS NOT NULL) "
"OR (tr.must_learn & 0x3 = 0)) "
"GROUP BY tr.id "
"HAVING sum(if(tre.item_id %s AND tre.iscontainer > 0,1,0)) > 0 AND SUM(tre.componentcount) <= %u "
"LIMIT 200 ",
CharacterID(), searchClause.c_str(),
rss->mintrivial, rss->maxtrivial, containers, combineObjectSlots);
TradeskillSearchResults(query, rss->object_type, rss->some_id);
return;
// TODO: Clean this up
std::string query = fmt::format(
SQL(
SELECT
tr.id,
tr.name,
tr.trivial,
SUM(tre.componentcount),
tr.tradeskill
FROM
tradeskill_recipe AS tr
LEFT JOIN tradeskill_recipe_entries AS tre ON tr.id = tre.recipe_id
WHERE
{} tr.trivial >= {}
AND tr.trivial <= {}
AND tr.enabled <> 0
AND tr.must_learn & 0x20 <> 0x20
AND (
(
tr.must_learn & 0x3 <> 0
)
OR (tr.must_learn & 0x3 = 0)
)
{}
GROUP BY
tr.id
HAVING
sum(
if (
tre.item_id {}
AND tre.iscontainer > 0,
1,
0
)
) > 0
AND SUM(tre.componentcount) <= {}
LIMIT
200
),
search_clause,
p_recipes_search_struct->mintrivial,
p_recipes_search_struct->maxtrivial,
ContentFilterCriteria::apply(),
containers_where_clause,
combine_object_slots
);
SendTradeskillSearchResults(query, p_recipes_search_struct->object_type, p_recipes_search_struct->some_id);
}
void Client::Handle_OP_ReloadUI(const EQApplicationPacket *app)
@@ -12375,7 +12441,7 @@ void Client::Handle_OP_SetStartCity(const EQApplicationPacket *app)
{
// if the character has a start city, don't let them use the command
if (m_pp.binds[4].zoneId != 0 && m_pp.binds[4].zoneId != 189) {
Message(Chat::Yellow, "Your home city has already been set.", m_pp.binds[4].zoneId, database.GetZoneName(m_pp.binds[4].zoneId));
Message(Chat::Yellow, "Your home city has already been set.", m_pp.binds[4].zoneId, ZoneName(m_pp.binds[4].zoneId));
return;
}
@@ -12389,10 +12455,15 @@ void Client::Handle_OP_SetStartCity(const EQApplicationPacket *app)
uint32 zoneid = 0;
uint32 startCity = (uint32)strtol((const char*)app->pBuffer, nullptr, 10);
std::string query = StringFormat("SELECT zone_id, bind_id, x, y, z FROM start_zones "
"WHERE player_class=%i AND player_deity=%i AND player_race=%i",
m_pp.class_, m_pp.deity, m_pp.race);
auto results = database.QueryDatabase(query);
std::string query = StringFormat(
"SELECT zone_id, bind_id, x, y, z FROM start_zones "
"WHERE player_class=%i AND player_deity=%i AND player_race=%i %s",
m_pp.class_,
m_pp.deity,
m_pp.race,
ContentFilterCriteria::apply().c_str()
);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
LogError("No valid start zones found for /setstartcity");
return;
@@ -12423,7 +12494,7 @@ void Client::Handle_OP_SetStartCity(const EQApplicationPacket *app)
query = StringFormat("SELECT zone_id, bind_id FROM start_zones "
"WHERE player_class=%i AND player_deity=%i AND player_race=%i",
m_pp.class_, m_pp.deity, m_pp.race);
results = database.QueryDatabase(query);
results = content_db.QueryDatabase(query);
if (!results.Success())
return;
@@ -12436,7 +12507,7 @@ void Client::Handle_OP_SetStartCity(const EQApplicationPacket *app)
zoneid = atoi(row[0]);
char* name = nullptr;
database.GetZoneLongName(database.GetZoneName(zoneid), &name);
content_db.GetZoneLongName(ZoneName(zoneid), &name);
Message(Chat::Yellow, "%d - %s", zoneid, name);
}
+3 -2
View File
@@ -53,6 +53,7 @@
#include "worldserver.h"
#include "zone.h"
#include "zonedb.h"
#include "zone_store.h"
extern QueryServ* QServ;
extern Zone* zone;
@@ -129,7 +130,7 @@ bool Client::Process() {
CheckManaEndUpdate();
if (dead && dead_timer.Check()) {
database.MoveCharacterToZone(GetName(), database.GetZoneName(m_pp.binds[0].zoneId));
database.MoveCharacterToZone(GetName(), m_pp.binds[0].zoneId);
m_pp.zone_id = m_pp.binds[0].zoneId;
m_pp.zoneInstance = m_pp.binds[0].instance_id;
@@ -2087,7 +2088,7 @@ void Client::HandleRespawnFromHover(uint32 Option)
m_pp.zone_id = chosen->zone_id;
m_pp.zoneInstance = chosen->instance_id;
database.MoveCharacterToZone(CharacterID(), database.GetZoneName(chosen->zone_id));
database.MoveCharacterToZone(CharacterID(), chosen->zone_id);
Save();
+481 -250
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -71,6 +71,7 @@ void command_chat(Client *c, const Seperator *sep);
void command_checklos(Client *c, const Seperator *sep);
void command_clearinvsnapshots(Client *c, const Seperator *sep);
void command_connectworldserver(Client *c, const Seperator *sep);
void command_copycharacter(Client *c, const Seperator *sep);
void command_corpse(Client *c, const Seperator *sep);
void command_corpsefix(Client *c, const Seperator *sep);
void command_crashtest(Client *c, const Seperator *sep);
@@ -112,6 +113,7 @@ void command_flymode(Client *c, const Seperator *sep);
void command_fov(Client *c, const Seperator *sep);
void command_freeze(Client *c, const Seperator *sep);
void command_gassign(Client *c, const Seperator *sep);
void command_gearup(Client *c, const Seperator *sep);
void command_gender(Client *c, const Seperator *sep);
void command_getplayerburiedcorpsecount(Client *c, const Seperator *sep);
void command_getvariable(Client *c, const Seperator *sep);
@@ -248,7 +250,6 @@ void command_reloadworld(Client *c, const Seperator *sep);
void command_reloadworldrules(Client *c, const Seperator *sep);
void command_reloadzps(Client *c, const Seperator *sep);
void command_repop(Client *c, const Seperator *sep);
void command_repopclose(Client *c, const Seperator *sep);
void command_resetaa(Client* c,const Seperator *sep);
void command_resetaa_timer(Client *c, const Seperator *sep);
void command_revoke(Client *c, const Seperator *sep);
+10 -11
View File
@@ -141,7 +141,7 @@ Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std:
pc->consented_guild_id = guild_consent_id;
pc->UpdateEquipmentLight(); // itemlist populated above..need to determine actual values
safe_delete_array(pcs);
return pc;
@@ -339,7 +339,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
// TODO soulbound items need not be added to corpse, but they need
// to go into the regular slots on the player, out of bags
std::list<uint32> removed_list;
// ideally, we would start at invslot::slotGeneral1 and progress to invslot::slotCursor..
// ..then regress and process invslot::EQUIPMENT_BEGIN through invslot::EQUIPMENT_END...
// without additional work to database loading of player corpses, this order is not
@@ -837,7 +837,7 @@ bool Corpse::Process() {
spc->zone_id = zone->graveyard_zoneid();
worldserver.SendPacket(pack);
safe_delete(pack);
LogDebug("Moved [{}] player corpse to the designated graveyard in zone [{}]", this->GetName(), database.GetZoneName(zone->graveyard_zoneid()));
LogDebug("Moved [{}] player corpse to the designated graveyard in zone [{}]", this->GetName(), ZoneName(zone->graveyard_zoneid()));
corpse_db_id = 0;
}
@@ -941,7 +941,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
SendLootReqErrorPacket(client, LootResponse::TooFar);
return;
}
if (being_looted_by != 0xFFFFFFFF && being_looted_by != client->GetID()) {
SendLootReqErrorPacket(client, LootResponse::SomeoneElse);
return;
@@ -1078,16 +1078,15 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
auto loot_slot = EQ::invslot::CORPSE_BEGIN;
auto corpse_mask = client->GetInv().GetLookup()->CorpseBitmask;
for (auto item_data : itemlist) {
// every loot session must either set all items' lootslots to 'invslot::SLOT_INVALID'
// or to a valid enumerated client-versioned corpse slot (lootslot is not equip_slot)
item_data->lootslot = 0xFFFF;
// align server and client corpse slot mappings so translators can function properly
while (loot_slot <= EQ::invslot::CORPSE_END && (((uint64)1 << loot_slot) & corpse_mask) == 0)
++loot_slot;
if (loot_slot > EQ::invslot::CORPSE_END)
continue;
@@ -1098,7 +1097,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
if (item_data->equip_slot < EQ::invslot::POSSESSIONS_BEGIN || item_data->equip_slot > EQ::invslot::POSSESSIONS_END)
continue;
}
const auto *item = database.GetItem(item_data->item_id);
auto inst = database.CreateItem(
item,
@@ -1121,7 +1120,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
client->SendItemPacket(loot_slot, inst, ItemPacketLoot);
safe_delete(inst);
item_data->lootslot = loot_slot++;
}
@@ -1581,14 +1580,14 @@ void Corpse::UpdateEquipmentLight()
if (EQ::lightsource::IsLevelGreater(item->Light, m_Light.Type[EQ::lightsource::LightEquipment]))
m_Light.Type[EQ::lightsource::LightEquipment] = item->Light;
}
uint8 general_light_type = 0;
for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) {
if ((*iter)->equip_slot < EQ::invslot::GENERAL_BEGIN || (*iter)->equip_slot > EQ::invslot::GENERAL_END) { continue; }
auto item = database.GetItem((*iter)->item_id);
if (item == nullptr) { continue; }
if (!item->IsClassCommon()) { continue; }
if (item->Light < 9 || item->Light > 13) { continue; }
+2 -1
View File
@@ -2,6 +2,7 @@
#include <utility>
#include "../common/string_util.h"
#include "zonedb.h"
#include "zone_store.h"
#include <ctime>
#include <cctype>
#include <algorithm>
@@ -172,4 +173,4 @@ uint32 DataBucket::ParseStringTimeToInt(std::string time_string)
duration = unit * 31556926;
return duration;
}
}
+13 -9
View File
@@ -28,6 +28,8 @@
#include "string_ids.h"
#include "worldserver.h"
#include "zonedb.h"
#include "zone_store.h"
#include "../common/repositories/criteria/content_filter_criteria.h"
#include <iostream>
#include <string.h>
@@ -83,8 +85,8 @@ Doors::Doors(const char *model, const glm::vec4 &position, uint8 open_type, uint
strn0cpy(door_name, model, 32);
strn0cpy(destination_zone_name, "NONE", 32);
this->database_id = (uint32) database.GetDoorsCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion());
this->door_id = (uint8) database.GetDoorsDBCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion());
this->database_id = (uint32) content_db.GetDoorsCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion());
this->door_id = (uint8) content_db.GetDoorsDBCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion());
this->open_type = open_type;
this->size = size;
@@ -451,7 +453,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger) {
if (!disable_add_to_key_ring) {
sender->KeyRingAdd(player_key);
}
if (database.GetZoneID(destination_zone_name) == zone->GetZoneID()) {
if (ZoneID(destination_zone_name) == zone->GetZoneID()) {
sender->MovePC(
zone->GetZoneID(),
zone->GetInstanceID(),
@@ -462,7 +464,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger) {
);
} else {
sender->MovePC(
database.GetZoneID(destination_zone_name),
ZoneID(destination_zone_name),
static_cast<uint32>(destination_instance_id),
m_Destination.x,
m_Destination.y,
@@ -473,7 +475,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger) {
}
if ((!IsDoorOpen() || open_type == 58) && (!required_key_item)) {
if (database.GetZoneID(destination_zone_name) == zone->GetZoneID()) {
if (ZoneID(destination_zone_name) == zone->GetZoneID()) {
sender->MovePC(
zone->GetZoneID(),
zone->GetInstanceID(),
@@ -484,7 +486,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger) {
);
} else {
sender->MovePC(
database.GetZoneID(destination_zone_name),
ZoneID(destination_zone_name),
static_cast<uint32>(this->destination_instance_id),
m_Destination.x,
m_Destination.y,
@@ -716,10 +718,12 @@ bool ZoneDatabase::LoadDoors(int32 door_count, Door *into, const char *zone_name
" WHERE "
" zone = '%s' "
" AND ( version = % u OR version = - 1 ) "
" %s "
" ORDER BY "
" doorid ASC ",
zone_name,
version
version,
ContentFilterCriteria::apply().c_str()
);
auto results = QueryDatabase(query);
if (!results.Success()) {
@@ -820,14 +824,14 @@ void Doors::SetDisableTimer(bool flag) {
void Doors::CreateDatabaseEntry()
{
if (database.GetDoorsDBCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion()) - 1 >= 255) {
if (content_db.GetDoorsDBCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion()) - 1 >= 255) {
return;
}
/**
* Persist
*/
database.InsertDoor(
content_db.InsertDoor(
GetDoorDBID(),
GetDoorID(),
GetDoorName(),
+2 -1
View File
@@ -28,6 +28,7 @@
#include "string_ids.h"
#include "worldserver.h"
#include "zonedb.h"
#include "zone_store.h"
#include "position.h"
float Mob::GetActSpellRange(uint16 spell_id, float range, bool IsBard)
@@ -554,7 +555,7 @@ int Client::GetDiscSlotBySpellID(int32 spellid)
if(m_pp.disciplines.values[i] == spellid)
return i;
}
return -1;
}
+746 -5
View File
@@ -17,6 +17,7 @@
*/
#include "../common/features.h"
#include "../common/content/world_content_service.h"
#ifdef EMBPERL
#ifdef EMBPERL_XS
@@ -2913,7 +2914,7 @@ XS(XS__countitem) {
}
XS(XS__getitemname);
XS(XS__getitemname) {
XS(XS__getitemname) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: quest::getitemname(uint32 item_id)");
@@ -3216,7 +3217,7 @@ XS(XS__CheckInstanceByCharID) {
if (items != 2) {
Perl_croak(aTHX_ "Usage: quest::CheckInstanceByCharID(uint16 instance_id, uint32 char_id)");
}
bool RETVAL;
dXSTARG;
@@ -5194,7 +5195,7 @@ XS(XS__log) {
else {
uint8 log_category = (uint8)SvIV(ST(0));
std::string log_message = (std::string) SvPV_nolen(ST(1));
if (log_category >= Logs::MaxCategoryID) {
return;
}
@@ -5263,11 +5264,11 @@ XS(XS__set_rule) {
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: quest::set_rule(string rule_name, string rule_value)");
std::string rule_name = (std::string) SvPV_nolen(ST(0));
std::string rule_value = (std::string) SvPV_nolen(ST(1));
RuleManager::Instance()->SetRule(rule_name.c_str(), rule_value.c_str());
XSRETURN_EMPTY;
}
@@ -5352,6 +5353,682 @@ XS(XS__delete_data) {
}
XS(XS__IsClassicEnabled);
XS(XS__IsClassicEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_classic_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsClassicEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsTheRuinsOfKunarkEnabled);
XS(XS__IsTheRuinsOfKunarkEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_the_ruins_of_kunark_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsTheRuinsOfKunarkEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsTheScarsOfVeliousEnabled);
XS(XS__IsTheScarsOfVeliousEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_the_scars_of_velious_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsTheScarsOfVeliousEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsTheShadowsOfLuclinEnabled);
XS(XS__IsTheShadowsOfLuclinEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_the_shadows_of_luclin_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsTheShadowsOfLuclinEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsThePlanesOfPowerEnabled);
XS(XS__IsThePlanesOfPowerEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_the_planes_of_power_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsThePlanesOfPowerEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsTheLegacyOfYkeshaEnabled);
XS(XS__IsTheLegacyOfYkeshaEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_the_legacy_of_ykesha_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsTheLegacyOfYkeshaEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsLostDungeonsOfNorrathEnabled);
XS(XS__IsLostDungeonsOfNorrathEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_lost_dungeons_of_norrath_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsLostDungeonsOfNorrathEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsGatesOfDiscordEnabled);
XS(XS__IsGatesOfDiscordEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_gates_of_discord_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsGatesOfDiscordEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsOmensOfWarEnabled);
XS(XS__IsOmensOfWarEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_omens_of_war_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsOmensOfWarEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsDragonsOfNorrathEnabled);
XS(XS__IsDragonsOfNorrathEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_dragons_of_norrath_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsDragonsOfNorrathEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsDepthsOfDarkhollowEnabled);
XS(XS__IsDepthsOfDarkhollowEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_depths_of_darkhollow_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsDepthsOfDarkhollowEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsProphecyOfRoEnabled);
XS(XS__IsProphecyOfRoEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_prophecy_of_ro_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsProphecyOfRoEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsTheSerpentsSpineEnabled);
XS(XS__IsTheSerpentsSpineEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_the_serpents_spine_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsTheSerpentsSpineEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsTheBuriedSeaEnabled);
XS(XS__IsTheBuriedSeaEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_the_buried_sea_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsTheBuriedSeaEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsSecretsOfFaydwerEnabled);
XS(XS__IsSecretsOfFaydwerEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_secrets_of_faydwer_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsSecretsOfFaydwerEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsSeedsOfDestructionEnabled);
XS(XS__IsSeedsOfDestructionEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_seeds_of_destruction_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsSeedsOfDestructionEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsUnderfootEnabled);
XS(XS__IsUnderfootEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_underfoot_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsUnderfootEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsHouseOfThuleEnabled);
XS(XS__IsHouseOfThuleEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_house_of_thule_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsHouseOfThuleEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsVeilOfAlarisEnabled);
XS(XS__IsVeilOfAlarisEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_veil_of_alaris_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsVeilOfAlarisEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsRainOfFearEnabled);
XS(XS__IsRainOfFearEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_rain_of_fear_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsRainOfFearEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCallOfTheForsakenEnabled);
XS(XS__IsCallOfTheForsakenEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_call_of_the_forsaken_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCallOfTheForsakenEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsTheDarkendSeaEnabled);
XS(XS__IsTheDarkendSeaEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_the_darkend_sea_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsTheDarkendSeaEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsTheBrokenMirrorEnabled);
XS(XS__IsTheBrokenMirrorEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_the_broken_mirror_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsTheBrokenMirrorEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsEmpiresOfKunarkEnabled);
XS(XS__IsEmpiresOfKunarkEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_empires_of_kunark_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsEmpiresOfKunarkEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsRingOfScaleEnabled);
XS(XS__IsRingOfScaleEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_ring_of_scale_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsRingOfScaleEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsTheBurningLandsEnabled);
XS(XS__IsTheBurningLandsEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_the_burning_lands_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsTheBurningLandsEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsTormentOfVeliousEnabled);
XS(XS__IsTormentOfVeliousEnabled) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_torment_of_velious_enabled()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsTormentOfVeliousEnabled();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionClassic);
XS(XS__IsCurrentExpansionClassic) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_classic()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionClassic();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionTheRuinsOfKunark);
XS(XS__IsCurrentExpansionTheRuinsOfKunark) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_ruins_of_kunark()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionTheRuinsOfKunark();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionTheScarsOfVelious);
XS(XS__IsCurrentExpansionTheScarsOfVelious) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_scars_of_velious()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionTheScarsOfVelious();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionTheShadowsOfLuclin);
XS(XS__IsCurrentExpansionTheShadowsOfLuclin) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_shadows_of_luclin()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionTheShadowsOfLuclin();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionThePlanesOfPower);
XS(XS__IsCurrentExpansionThePlanesOfPower) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_planes_of_power()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionThePlanesOfPower();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionTheLegacyOfYkesha);
XS(XS__IsCurrentExpansionTheLegacyOfYkesha) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_legacy_of_ykesha()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionTheLegacyOfYkesha();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionLostDungeonsOfNorrath);
XS(XS__IsCurrentExpansionLostDungeonsOfNorrath) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_lost_dungeons_of_norrath()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionLostDungeonsOfNorrath();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionGatesOfDiscord);
XS(XS__IsCurrentExpansionGatesOfDiscord) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_gates_of_discord()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionGatesOfDiscord();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionOmensOfWar);
XS(XS__IsCurrentExpansionOmensOfWar) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_omens_of_war()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionOmensOfWar();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionDragonsOfNorrath);
XS(XS__IsCurrentExpansionDragonsOfNorrath) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_dragons_of_norrath()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionDragonsOfNorrath();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionDepthsOfDarkhollow);
XS(XS__IsCurrentExpansionDepthsOfDarkhollow) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_depths_of_darkhollow()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionDepthsOfDarkhollow();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionProphecyOfRo);
XS(XS__IsCurrentExpansionProphecyOfRo) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_prophecy_of_ro()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionProphecyOfRo();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionTheSerpentsSpine);
XS(XS__IsCurrentExpansionTheSerpentsSpine) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_serpents_spine()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionTheSerpentsSpine();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionTheBuriedSea);
XS(XS__IsCurrentExpansionTheBuriedSea) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_buried_sea()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionTheBuriedSea();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionSecretsOfFaydwer);
XS(XS__IsCurrentExpansionSecretsOfFaydwer) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_secrets_of_faydwer()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionSecretsOfFaydwer();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionSeedsOfDestruction);
XS(XS__IsCurrentExpansionSeedsOfDestruction) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_seeds_of_destruction()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionSeedsOfDestruction();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionUnderfoot);
XS(XS__IsCurrentExpansionUnderfoot) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_underfoot()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionUnderfoot();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionHouseOfThule);
XS(XS__IsCurrentExpansionHouseOfThule) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_house_of_thule()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionHouseOfThule();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionVeilOfAlaris);
XS(XS__IsCurrentExpansionVeilOfAlaris) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_veil_of_alaris()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionVeilOfAlaris();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionRainOfFear);
XS(XS__IsCurrentExpansionRainOfFear) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_rain_of_fear()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionRainOfFear();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionCallOfTheForsaken);
XS(XS__IsCurrentExpansionCallOfTheForsaken) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_call_of_the_forsaken()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionCallOfTheForsaken();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionTheDarkendSea);
XS(XS__IsCurrentExpansionTheDarkendSea) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_darkend_sea()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionTheDarkendSea();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionTheBrokenMirror);
XS(XS__IsCurrentExpansionTheBrokenMirror) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_broken_mirror()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionTheBrokenMirror();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionEmpiresOfKunark);
XS(XS__IsCurrentExpansionEmpiresOfKunark) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_empires_of_kunark()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionEmpiresOfKunark();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionRingOfScale);
XS(XS__IsCurrentExpansionRingOfScale) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_ring_of_scale()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionRingOfScale();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionTheBurningLands);
XS(XS__IsCurrentExpansionTheBurningLands) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_the_burning_lands()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionTheBurningLands();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsCurrentExpansionTormentOfVelious);
XS(XS__IsCurrentExpansionTormentOfVelious) {
dXSARGS;
if (items >= 1) {
Perl_croak(aTHX_ "Usage: quest::is_current_expansion_torment_of_velious()");
}
bool RETVAL; dXSTARG;
RETVAL = content_service.IsCurrentExpansionTormentOfVelious();
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__IsContentFlagEnabled);
XS(XS__IsContentFlagEnabled) {
dXSARGS;
if (items != 1) {
Perl_croak(aTHX_ "Usage: quest::is_content_flag_enabled(string flag_name)");
}
std::string flag_name = (std::string) SvPV_nolen(ST(0));
bool RETVAL; dXSTARG;
RETVAL = content_service.IsContentFlagEnabled(flag_name);
XSprePUSH; PUSHu((IV) RETVAL); XSRETURN(1);
}
XS(XS__SetContentFlag);
XS(XS__SetContentFlag)
{
dXSARGS;
if (items != 2) {
Perl_croak(aTHX_ "Usage: quest::set_content_flag(string flag_name, enabled)");
}
std::string flag_name = (std::string) SvPV_nolen(ST(0));
bool enabled = (int) SvIV(ST(1)) != 0;
ZoneStore::SetContentFlag(flag_name, enabled);
XSRETURN_EMPTY;
}
/*
This is the callback perl will look for to setup the
quest package's XSUBs
@@ -5692,6 +6369,70 @@ EXTERN_C XS(boot_quest) {
newXS(strcpy(buf, "zonegroup"), XS__zonegroup, file);
newXS(strcpy(buf, "zoneraid"), XS__zoneraid, file);
/**
* Expansions
*/
newXS(strcpy(buf, "is_classic_enabled"), XS__IsClassicEnabled, file);
newXS(strcpy(buf, "is_the_ruins_of_kunark_enabled"), XS__IsTheRuinsOfKunarkEnabled, file);
newXS(strcpy(buf, "is_the_scars_of_velious_enabled"), XS__IsTheScarsOfVeliousEnabled, file);
newXS(strcpy(buf, "is_the_shadows_of_luclin_enabled"), XS__IsTheShadowsOfLuclinEnabled, file);
newXS(strcpy(buf, "is_the_planes_of_power_enabled"), XS__IsThePlanesOfPowerEnabled, file);
newXS(strcpy(buf, "is_the_legacy_of_ykesha_enabled"), XS__IsTheLegacyOfYkeshaEnabled, file);
newXS(strcpy(buf, "is_lost_dungeons_of_norrath_enabled"), XS__IsLostDungeonsOfNorrathEnabled, file);
newXS(strcpy(buf, "is_gates_of_discord_enabled"), XS__IsGatesOfDiscordEnabled, file);
newXS(strcpy(buf, "is_omens_of_war_enabled"), XS__IsOmensOfWarEnabled, file);
newXS(strcpy(buf, "is_dragons_of_norrath_enabled"), XS__IsDragonsOfNorrathEnabled, file);
newXS(strcpy(buf, "is_depths_of_darkhollow_enabled"), XS__IsDepthsOfDarkhollowEnabled, file);
newXS(strcpy(buf, "is_prophecy_of_ro_enabled"), XS__IsProphecyOfRoEnabled, file);
newXS(strcpy(buf, "is_the_serpents_spine_enabled"), XS__IsTheSerpentsSpineEnabled, file);
newXS(strcpy(buf, "is_the_buried_sea_enabled"), XS__IsTheBuriedSeaEnabled, file);
newXS(strcpy(buf, "is_secrets_of_faydwer_enabled"), XS__IsSecretsOfFaydwerEnabled, file);
newXS(strcpy(buf, "is_seeds_of_destruction_enabled"), XS__IsSeedsOfDestructionEnabled, file);
newXS(strcpy(buf, "is_underfoot_enabled"), XS__IsUnderfootEnabled, file);
newXS(strcpy(buf, "is_house_of_thule_enabled"), XS__IsHouseOfThuleEnabled, file);
newXS(strcpy(buf, "is_veil_of_alaris_enabled"), XS__IsVeilOfAlarisEnabled, file);
newXS(strcpy(buf, "is_rain_of_fear_enabled"), XS__IsRainOfFearEnabled, file);
newXS(strcpy(buf, "is_call_of_the_forsaken_enabled"), XS__IsCallOfTheForsakenEnabled, file);
newXS(strcpy(buf, "is_the_darkend_sea_enabled"), XS__IsTheDarkendSeaEnabled, file);
newXS(strcpy(buf, "is_the_broken_mirror_enabled"), XS__IsTheBrokenMirrorEnabled, file);
newXS(strcpy(buf, "is_empires_of_kunark_enabled"), XS__IsEmpiresOfKunarkEnabled, file);
newXS(strcpy(buf, "is_ring_of_scale_enabled"), XS__IsRingOfScaleEnabled, file);
newXS(strcpy(buf, "is_the_burning_lands_enabled"), XS__IsTheBurningLandsEnabled, file);
newXS(strcpy(buf, "is_torment_of_velious_enabled"), XS__IsTormentOfVeliousEnabled, file);
newXS(strcpy(buf, "is_current_expansion_classic"), XS__IsCurrentExpansionClassic, file);
newXS(strcpy(buf, "is_current_expansion_the_ruins_of_kunark"), XS__IsCurrentExpansionTheRuinsOfKunark, file);
newXS(strcpy(buf, "is_current_expansion_the_scars_of_velious"), XS__IsCurrentExpansionTheScarsOfVelious, file);
newXS(strcpy(buf, "is_current_expansion_the_shadows_of_luclin"), XS__IsCurrentExpansionTheShadowsOfLuclin, file);
newXS(strcpy(buf, "is_current_expansion_the_planes_of_power"), XS__IsCurrentExpansionThePlanesOfPower, file);
newXS(strcpy(buf, "is_current_expansion_the_legacy_of_ykesha"), XS__IsCurrentExpansionTheLegacyOfYkesha, file);
newXS(strcpy(buf, "is_current_expansion_lost_dungeons_of_norrath"), XS__IsCurrentExpansionLostDungeonsOfNorrath, file);
newXS(strcpy(buf, "is_current_expansion_gates_of_discord"), XS__IsCurrentExpansionGatesOfDiscord, file);
newXS(strcpy(buf, "is_current_expansion_omens_of_war"), XS__IsCurrentExpansionOmensOfWar, file);
newXS(strcpy(buf, "is_current_expansion_dragons_of_norrath"), XS__IsCurrentExpansionDragonsOfNorrath, file);
newXS(strcpy(buf, "is_current_expansion_depths_of_darkhollow"), XS__IsCurrentExpansionDepthsOfDarkhollow, file);
newXS(strcpy(buf, "is_current_expansion_prophecy_of_ro"), XS__IsCurrentExpansionProphecyOfRo, file);
newXS(strcpy(buf, "is_current_expansion_the_serpents_spine"), XS__IsCurrentExpansionTheSerpentsSpine, file);
newXS(strcpy(buf, "is_current_expansion_the_buried_sea"), XS__IsCurrentExpansionTheBuriedSea, file);
newXS(strcpy(buf, "is_current_expansion_secrets_of_faydwer"), XS__IsCurrentExpansionSecretsOfFaydwer, file);
newXS(strcpy(buf, "is_current_expansion_seeds_of_destruction"), XS__IsCurrentExpansionSeedsOfDestruction, file);
newXS(strcpy(buf, "is_current_expansion_underfoot"), XS__IsCurrentExpansionUnderfoot, file);
newXS(strcpy(buf, "is_current_expansion_house_of_thule"), XS__IsCurrentExpansionHouseOfThule, file);
newXS(strcpy(buf, "is_current_expansion_veil_of_alaris"), XS__IsCurrentExpansionVeilOfAlaris, file);
newXS(strcpy(buf, "is_current_expansion_rain_of_fear"), XS__IsCurrentExpansionRainOfFear, file);
newXS(strcpy(buf, "is_current_expansion_call_of_the_forsaken"), XS__IsCurrentExpansionCallOfTheForsaken, file);
newXS(strcpy(buf, "is_current_expansion_the_darkend_sea"), XS__IsCurrentExpansionTheDarkendSea, file);
newXS(strcpy(buf, "is_current_expansion_the_broken_mirror"), XS__IsCurrentExpansionTheBrokenMirror, file);
newXS(strcpy(buf, "is_current_expansion_empires_of_kunark"), XS__IsCurrentExpansionEmpiresOfKunark, file);
newXS(strcpy(buf, "is_current_expansion_ring_of_scale"), XS__IsCurrentExpansionRingOfScale, file);
newXS(strcpy(buf, "is_current_expansion_the_burning_lands"), XS__IsCurrentExpansionTheBurningLands, file);
newXS(strcpy(buf, "is_current_expansion_torment_of_velious"), XS__IsCurrentExpansionTormentOfVelious, file);
/**
* Content flags
*/
newXS(strcpy(buf, "is_content_flag_enabled"), XS__IsContentFlagEnabled, file);
newXS(strcpy(buf, "set_content_flag"), XS__SetContentFlag, file);
XSRETURN_YES;
}
+42 -9
View File
@@ -30,6 +30,8 @@
#include "titles.h"
#include "water_map.h"
#include "zonedb.h"
#include "zone_store.h"
#include "../common/repositories/criteria/content_filter_criteria.h"
#include <iostream>
@@ -54,9 +56,25 @@ uint32 ZoneDatabase::GetZoneForage(uint32 ZoneID, uint8 skill) {
}
uint32 chancepool = 0;
std::string query = StringFormat("SELECT itemid, chance FROM "
"forage WHERE zoneid = '%i' and level <= '%i' "
"LIMIT %i", ZoneID, skill, FORAGE_ITEM_LIMIT);
std::string query = fmt::format(
SQL(
SELECT
itemid,
chance
FROM
forage
WHERE
zoneid = '{}'
and level <= '{}'
{}
LIMIT
{}
),
ZoneID,
skill,
ContentFilterCriteria::apply(),
FORAGE_ITEM_LIMIT
);
auto results = QueryDatabase(query);
if (!results.Success()) {
return 0;
@@ -109,9 +127,24 @@ uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id,
chance[c]=0;
}
std::string query = StringFormat("SELECT itemid, chance, npc_id, npc_chance "
"FROM fishing WHERE (zoneid = '%i' || zoneid = 0) AND skill_level <= '%i'",
ZoneID, skill);
std::string query = fmt::format(
SQL(
SELECT
itemid,
chance,
npc_id,
npc_chance
FROM
fishing
WHERE
(zoneid = '{}' || zoneid = 0)
AND skill_level <= '{}'
{}
),
ZoneID,
skill,
ContentFilterCriteria::apply()
);
auto results = QueryDatabase(query);
if (!results.Success()) {
return 0;
@@ -274,13 +307,13 @@ void Client::GoFish()
if (zone->random.Int(0, 399) <= fishing_skill ) {
uint32 npc_id = 0;
uint8 npc_chance = 0;
food_id = database.GetZoneFishing(m_pp.zone_id, fishing_skill, npc_id, npc_chance);
food_id = content_db.GetZoneFishing(m_pp.zone_id, fishing_skill, npc_id, npc_chance);
//check for add NPC
if (npc_chance > 0 && npc_id) {
if (zone->random.Roll(npc_chance)) {
if (zone->CanDoCombat()) {
const NPCType *tmp = database.LoadNPCTypesData(npc_id);
const NPCType *tmp = content_db.LoadNPCTypesData(npc_id);
if (tmp != nullptr) {
auto positionNPC = GetPosition();
positionNPC.x = positionNPC.x + 3;
@@ -407,7 +440,7 @@ void Client::ForageItem(bool guarantee) {
uint32 stringid = FORAGE_NOEAT;
if (zone->random.Roll(25)) {
foragedfood = database.GetZoneForage(m_pp.zone_id, skill_level);
foragedfood = content_db.GetZoneForage(m_pp.zone_id, skill_level);
}
//not an else in case theres no DB food
-32
View File
@@ -408,35 +408,3 @@ void Client::GuildChangeRank(const char* name, uint32 guild_id, uint32 oldrank,
SendGuildMembers(guild_id, true);
}*/
bool ZoneDatabase::CheckGuildDoor(uint8 doorid, uint16 guild_id, const char* zone) {
std::string query = StringFormat("SELECT guild FROM doors WHERE doorid = %i AND zone = '%s'",
doorid-128, zone);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
if (results.RowCount() != 1)
return false;
auto row = results.begin();
return atoi(row[0]) == guild_id;
}
bool ZoneDatabase::SetGuildDoor(uint8 doorid,uint16 guild_id, const char* zone) {
if (doorid > 127)
doorid = doorid - 128;
std::string query = StringFormat("UPDATE doors SET guild = %i WHERE (doorid=%i) AND (zone='%s')",
guild_id, doorid, zone);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
return (results.RowsAffected() > 0);
}
+1
View File
@@ -24,6 +24,7 @@
#include "guild_mgr.h"
#include "worldserver.h"
#include "zonedb.h"
#include "zone_store.h"
ZoneGuildManager guild_mgr;
GuildBankManager *GuildBanks;
+1 -1
View File
@@ -73,7 +73,7 @@ const NPCType *Horse::BuildHorseType(uint16 spell_id) {
const char* fileName = spells[spell_id].teleport_zone;
std::string query = StringFormat("SELECT race, gender, texture, mountspeed FROM horses WHERE filename = '%s'", fileName);
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
return nullptr;
}
+20 -19
View File
@@ -23,6 +23,7 @@
#include "quest_parser_collection.h"
#include "worldserver.h"
#include "zonedb.h"
#include "zone_store.h"
extern WorldServer worldserver;
@@ -231,7 +232,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
bool enforcewear = RuleB(Inventory, EnforceAugmentWear);
bool enforcerestr = RuleB(Inventory, EnforceAugmentRestriction);
bool enforceusable = RuleB(Inventory, EnforceAugmentUsability);
for (int iter = EQ::invaug::SOCKET_BEGIN; iter <= EQ::invaug::SOCKET_END; ++iter) {
const EQ::ItemData* augtest = database.GetItem(augments[iter]);
@@ -249,7 +250,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
if(CheckLoreConflict(augtest)) {
// DuplicateLoreMessage(augtest->ID);
Message(Chat::Red, "You already have a lore %s (%u) in your inventory.", augtest->Name, augtest->ID);
return false;
}
// check that augment is an actual augment
@@ -257,7 +258,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
Message(Chat::Red, "%s (%u) (Aug%i) is not an actual augment.", augtest->Name, augtest->ID, iter + 1);
LogInventory("Player [{}] on account [{}] attempted to use a non-augment item (Aug[{}]) as an augment.\n(Item: [{}], Aug1: [{}], Aug2: [{}], Aug3: [{}], Aug4: [{}], Aug5: [{}], Aug6: [{}])\n",
GetName(), account_name, item->ID, (iter + 1), aug1, aug2, aug3, aug4, aug5, aug6);
return false;
}
@@ -504,7 +505,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
// validation passed..so, set the charges and create the actual item
// if the item is stackable and the charge amount is -1 or 0 then set to 1 charge.
// removed && item->MaxCharges == 0 if -1 or 0 was passed max charges is irrelevant
// removed && item->MaxCharges == 0 if -1 or 0 was passed max charges is irrelevant
if(charges <= 0 && item->Stackable)
charges = 1;
@@ -534,7 +535,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
// attune item
if(attuned && inst->GetItem()->Attuneable)
inst->SetAttuned(true);
inst->SetOrnamentIcon(ornament_icon);
inst->SetOrnamentationIDFile(ornament_idfile);
inst->SetOrnamentHeroModel(ornament_hero_model);
@@ -584,7 +585,7 @@ void Client::DropItem(int16 slot_id, bool recurse)
{
LogInventory("[{}] (char_id: [{}]) Attempting to drop item from slot [{}] on the ground",
GetCleanName(), CharacterID(), slot_id);
if(GetInv().CheckNoDrop(slot_id, recurse) && RuleI(World, FVNoDropFlag) == 0 ||
RuleI(Character, MinStatusForNoDropExemptions) < Admin() && RuleI(World, FVNoDropFlag) == 2)
{
@@ -1016,7 +1017,7 @@ bool Client::PutItemInInventory(int16 slot_id, const EQ::ItemInstance& inst, boo
SendItemPacket(slot_id, &inst, ((slot_id == EQ::invslot::slotCursor) ? ItemPacketLimbo : ItemPacketTrade));
//SendWearChange(EQ::InventoryProfile::CalcMaterialFromSlot(slot_id));
}
if (slot_id == EQ::invslot::slotCursor) {
auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend();
return database.SaveCursor(this->CharacterID(), s, e);
@@ -1054,7 +1055,7 @@ void Client::PutLootInInventory(int16 slot_id, const EQ::ItemInstance &inst, Ser
else {
SendLootItemInPacket(&inst, slot_id);
}
if (bag_item_data) {
for (int index = EQ::invbag::SLOT_BEGIN; index <= EQ::invbag::SLOT_END; ++index) {
if (bag_item_data[index] == nullptr)
@@ -1168,7 +1169,7 @@ bool Client::AutoPutLootInInventory(EQ::ItemInstance& inst, bool try_worn, bool
if (worn_slot_material != EQ::textures::materialInvalid) {
SendWearChange(worn_slot_material);
}
parse->EventItem(EVENT_EQUIP_ITEM, this, &inst, nullptr, "", i);
return true;
}
@@ -1245,7 +1246,7 @@ bool MakeItemLink(char* &ret_link, const ItemData *item, uint32 aug0, uint32 aug
//int hash = GetItemLinkHash(inst); //eventually this will work (currently crashes zone), but for now we'll skip the extra overhead
int hash = NOT_USED;
// Tested with UF and RoF..there appears to be a problem with using non-augment arguments below...
// Currently, enabling them causes misalignments in what the client expects. I haven't looked
// into it further to determine the cause..but, the function is setup to accept the parameters.
@@ -1935,7 +1936,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
fail_message = "Your class, deity and/or race may not equip that item.";
else if (fail_state == EQ::InventoryProfile::swapLevel)
fail_message = "You are not sufficient level to use this item.";
if (fail_message)
Message(Chat::Red, "%s", fail_message);
@@ -2203,7 +2204,7 @@ void Client::DyeArmor(EQ::TintProfile* dye){
EQ::ItemInstance* inst = this->m_inv.GetItem(slot2);
if(inst){
uint32 armor_color = ((uint32)dye->Slot[i].Red << 16) | ((uint32)dye->Slot[i].Green << 8) | ((uint32)dye->Slot[i].Blue);
inst->SetColor(armor_color);
inst->SetColor(armor_color);
database.SaveCharacterMaterialColor(this->CharacterID(), i, armor_color);
database.SaveInventory(CharacterID(),inst,slot2);
if(dye->Slot[i].UseTint)
@@ -2225,7 +2226,7 @@ void Client::DyeArmor(EQ::TintProfile* dye){
auto outapp = new EQApplicationPacket(OP_Dye, 0);
QueuePacket(outapp);
safe_delete(outapp);
}
void Client::DyeArmorBySlot(uint8 slot, uint8 red, uint8 green, uint8 blue, uint8 use_tint) {
@@ -2334,7 +2335,7 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) {
for (x = EQ::invbag::CURSOR_BAG_BEGIN; x <= EQ::invbag::CURSOR_BAG_END; ++x) {
if (num >= amt)
break;
TempItem = nullptr;
ins = GetInv().GetItem(x);
if (ins)
@@ -2359,7 +2360,7 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) {
TempItem = ins->GetItem();
if (TempItem && TempItem->ID != type)
continue;
if (ins->GetCharges() < amt) {
amt -= ins->GetCharges();
DeleteItemInInventory(x, amt, true);
@@ -2550,7 +2551,7 @@ void Client::DisenchantSummonedBags(bool client_update)
if (!new_item) { continue; }
auto new_inst = database.CreateBaseItem(new_item);
if (!new_inst) { continue; }
if (CopyBagContents(new_inst, inst)) {
LogInventory("Disenchant Summoned Bags: Replacing [{}] with [{}] in slot [{}]", inst->GetItem()->Name, new_inst->GetItem()->Name, slot_id);
PutItemInInventory(slot_id, *new_inst, client_update);
@@ -2724,7 +2725,7 @@ void Client::RemoveDuplicateLore(bool client_update)
}
safe_delete(inst);
}
for (auto slot_id = EQ::invslot::GENERAL_BEGIN; slot_id <= EQ::invslot::GENERAL_END; ++slot_id) {
if (((uint64)1 << slot_id) & GetInv().GetLookup()->PossessionsBitmask == 0)
continue;
@@ -3028,7 +3029,7 @@ void Client::CreateBandolier(const EQApplicationPacket *app)
LogInventory("Char: [{}] Creating Bandolier Set [{}], Set Name: [{}]", GetName(), bs->Number, bs->Name);
strcpy(m_pp.bandoliers[bs->Number].Name, bs->Name);
const EQ::ItemInstance* InvItem = nullptr;
const EQ::ItemInstance* InvItem = nullptr;
const EQ::ItemData *BaseItem = nullptr;
int16 WeaponSlot = 0;
@@ -3059,7 +3060,7 @@ void Client::RemoveBandolier(const EQApplicationPacket *app)
memset(m_pp.bandoliers[bds->Number].Name, 0, 32);
for(int i = bandolierPrimary; i <= bandolierAmmo; i++) {
m_pp.bandoliers[bds->Number].Items[i].ID = 0;
m_pp.bandoliers[bds->Number].Items[i].Icon = 0;
m_pp.bandoliers[bds->Number].Items[i].Icon = 0;
}
database.DeleteCharacterBandolier(this->CharacterID(), bds->Number);
}
+42 -11
View File
@@ -26,7 +26,9 @@
#include "mob.h"
#include "npc.h"
#include "zonedb.h"
#include "zone_store.h"
#include "global_loot_manager.h"
#include "../common/repositories/criteria/content_filter_criteria.h"
#include <iostream>
#include <stdlib.h>
@@ -463,42 +465,70 @@ void NPC::CheckGlobalLootTables()
void ZoneDatabase::LoadGlobalLoot()
{
auto query = StringFormat("SELECT id, loottable_id, description, min_level, max_level, rare, raid, race, "
"class, bodytype, zone, hot_zone FROM global_loot WHERE enabled = 1");
auto query = fmt::format(
SQL
(
SELECT
id,
loottable_id,
description,
min_level,
max_level,
rare,
raid,
race,
class,
bodytype,
zone,
hot_zone
FROM
global_loot
WHERE
enabled = 1
{}
),
ContentFilterCriteria::apply()
);
auto results = QueryDatabase(query);
if (!results.Success() || results.RowCount() == 0)
if (!results.Success() || results.RowCount() == 0) {
return;
}
// we might need this, lets not keep doing it in a loop
auto zoneid = std::to_string(zone->GetZoneID());
for (auto row = results.begin(); row != results.end(); ++row) {
auto zoneid = std::to_string(zone->GetZoneID());
for (auto row = results.begin(); row != results.end(); ++row) {
// checking zone limits
if (row[10]) {
auto zones = SplitString(row[10], '|');
auto it = std::find(zones.begin(), zones.end(), zoneid);
if (it == zones.end()) // not in here, skip
if (it == zones.end()) { // not in here, skip
continue;
}
}
GlobalLootEntry e(atoi(row[0]), atoi(row[1]), row[2] ? row[2] : "");
auto min_level = atoi(row[3]);
if (min_level)
if (min_level) {
e.AddRule(GlobalLoot::RuleTypes::LevelMin, min_level);
}
auto max_level = atoi(row[4]);
if (max_level)
if (max_level) {
e.AddRule(GlobalLoot::RuleTypes::LevelMax, max_level);
}
// null is not used
if (row[5])
if (row[5]) {
e.AddRule(GlobalLoot::RuleTypes::Rare, atoi(row[5]));
}
// null is not used
if (row[6])
if (row[6]) {
e.AddRule(GlobalLoot::RuleTypes::Raid, atoi(row[6]));
}
if (row[7]) {
auto races = SplitString(row[7], '|');
@@ -522,8 +552,9 @@ void ZoneDatabase::LoadGlobalLoot()
}
// null is not used
if (row[11])
if (row[11]) {
e.AddRule(GlobalLoot::RuleTypes::HotZone, atoi(row[11]));
}
zone->AddGlobalLootEntry(e);
}
+294 -1
View File
@@ -7,6 +7,7 @@
#include <list>
#include <map>
#include "../common/content/world_content_service.h"
#include "../common/timer.h"
#include "../common/eqemu_logsys.h"
#include "../common/classes.h"
@@ -1937,6 +1938,234 @@ void lua_update_zone_header(std::string type, std::string value) {
quest_manager.UpdateZoneHeader(type, value);
}
/**
* Expansions
*/
bool lua_is_classic_enabled() {
return content_service.IsClassicEnabled();
}
bool lua_is_the_ruins_of_kunark_enabled() {
return content_service.IsTheRuinsOfKunarkEnabled();
}
bool lua_is_the_scars_of_velious_enabled() {
return content_service.IsTheScarsOfVeliousEnabled();
}
bool lua_is_the_shadows_of_luclin_enabled() {
return content_service.IsTheShadowsOfLuclinEnabled();
}
bool lua_is_the_planes_of_power_enabled() {
return content_service.IsThePlanesOfPowerEnabled();
}
bool lua_is_the_legacy_of_ykesha_enabled() {
return content_service.IsTheLegacyOfYkeshaEnabled();
}
bool lua_is_lost_dungeons_of_norrath_enabled() {
return content_service.IsLostDungeonsOfNorrathEnabled();
}
bool lua_is_gates_of_discord_enabled() {
return content_service.IsGatesOfDiscordEnabled();
}
bool lua_is_omens_of_war_enabled() {
return content_service.IsOmensOfWarEnabled();
}
bool lua_is_dragons_of_norrath_enabled() {
return content_service.IsDragonsOfNorrathEnabled();
}
bool lua_is_depths_of_darkhollow_enabled() {
return content_service.IsDepthsOfDarkhollowEnabled();
}
bool lua_is_prophecy_of_ro_enabled() {
return content_service.IsProphecyOfRoEnabled();
}
bool lua_is_the_serpents_spine_enabled() {
return content_service.IsTheSerpentsSpineEnabled();
}
bool lua_is_the_buried_sea_enabled() {
return content_service.IsTheBuriedSeaEnabled();
}
bool lua_is_secrets_of_faydwer_enabled() {
return content_service.IsSecretsOfFaydwerEnabled();
}
bool lua_is_seeds_of_destruction_enabled() {
return content_service.IsSeedsOfDestructionEnabled();
}
bool lua_is_underfoot_enabled() {
return content_service.IsUnderfootEnabled();
}
bool lua_is_house_of_thule_enabled() {
return content_service.IsHouseOfThuleEnabled();
}
bool lua_is_veil_of_alaris_enabled() {
return content_service.IsVeilOfAlarisEnabled();
}
bool lua_is_rain_of_fear_enabled() {
return content_service.IsRainOfFearEnabled();
}
bool lua_is_call_of_the_forsaken_enabled() {
return content_service.IsCallOfTheForsakenEnabled();
}
bool lua_is_the_darkend_sea_enabled() {
return content_service.IsTheDarkendSeaEnabled();
}
bool lua_is_the_broken_mirror_enabled() {
return content_service.IsTheBrokenMirrorEnabled();
}
bool lua_is_empires_of_kunark_enabled() {
return content_service.IsEmpiresOfKunarkEnabled();
}
bool lua_is_ring_of_scale_enabled() {
return content_service.IsRingOfScaleEnabled();
}
bool lua_is_the_burning_lands_enabled() {
return content_service.IsTheBurningLandsEnabled();
}
bool lua_is_torment_of_velious_enabled() {
return content_service.IsTormentOfVeliousEnabled();
}
bool lua_is_current_expansion_classic() {
return content_service.IsCurrentExpansionClassic();
}
bool lua_is_current_expansion_the_ruins_of_kunark() {
return content_service.IsCurrentExpansionTheRuinsOfKunark();
}
bool lua_is_current_expansion_the_scars_of_velious() {
return content_service.IsCurrentExpansionTheScarsOfVelious();
}
bool lua_is_current_expansion_the_shadows_of_luclin() {
return content_service.IsCurrentExpansionTheShadowsOfLuclin();
}
bool lua_is_current_expansion_the_planes_of_power() {
return content_service.IsCurrentExpansionThePlanesOfPower();
}
bool lua_is_current_expansion_the_legacy_of_ykesha() {
return content_service.IsCurrentExpansionTheLegacyOfYkesha();
}
bool lua_is_current_expansion_lost_dungeons_of_norrath() {
return content_service.IsCurrentExpansionLostDungeonsOfNorrath();
}
bool lua_is_current_expansion_gates_of_discord() {
return content_service.IsCurrentExpansionGatesOfDiscord();
}
bool lua_is_current_expansion_omens_of_war() {
return content_service.IsCurrentExpansionOmensOfWar();
}
bool lua_is_current_expansion_dragons_of_norrath() {
return content_service.IsCurrentExpansionDragonsOfNorrath();
}
bool lua_is_current_expansion_depths_of_darkhollow() {
return content_service.IsCurrentExpansionDepthsOfDarkhollow();
}
bool lua_is_current_expansion_prophecy_of_ro() {
return content_service.IsCurrentExpansionProphecyOfRo();
}
bool lua_is_current_expansion_the_serpents_spine() {
return content_service.IsCurrentExpansionTheSerpentsSpine();
}
bool lua_is_current_expansion_the_buried_sea() {
return content_service.IsCurrentExpansionTheBuriedSea();
}
bool lua_is_current_expansion_secrets_of_faydwer() {
return content_service.IsCurrentExpansionSecretsOfFaydwer();
}
bool lua_is_current_expansion_seeds_of_destruction() {
return content_service.IsCurrentExpansionSeedsOfDestruction();
}
bool lua_is_current_expansion_underfoot() {
return content_service.IsCurrentExpansionUnderfoot();
}
bool lua_is_current_expansion_house_of_thule() {
return content_service.IsCurrentExpansionHouseOfThule();
}
bool lua_is_current_expansion_veil_of_alaris() {
return content_service.IsCurrentExpansionVeilOfAlaris();
}
bool lua_is_current_expansion_rain_of_fear() {
return content_service.IsCurrentExpansionRainOfFear();
}
bool lua_is_current_expansion_call_of_the_forsaken() {
return content_service.IsCurrentExpansionCallOfTheForsaken();
}
bool lua_is_current_expansion_the_darkend_sea() {
return content_service.IsCurrentExpansionTheDarkendSea();
}
bool lua_is_current_expansion_the_broken_mirror() {
return content_service.IsCurrentExpansionTheBrokenMirror();
}
bool lua_is_current_expansion_empires_of_kunark() {
return content_service.IsCurrentExpansionEmpiresOfKunark();
}
bool lua_is_current_expansion_ring_of_scale() {
return content_service.IsCurrentExpansionRingOfScale();
}
bool lua_is_current_expansion_the_burning_lands() {
return content_service.IsCurrentExpansionTheBurningLands();
}
bool lua_is_current_expansion_torment_of_velious() {
return content_service.IsCurrentExpansionTormentOfVelious();
}
bool lua_is_content_flag_enabled(std::string content_flag){
return content_service.IsContentFlagEnabled(content_flag);
}
void lua_set_content_flag(std::string flag_name, bool enabled){
ZoneStore::SetContentFlag(flag_name, enabled);
}
#define LuaCreateNPCParse(name, c_type, default_value) do { \
cur = table[#name]; \
if(luabind::type(cur) != LUA_TNIL) { \
@@ -2467,7 +2696,71 @@ luabind::scope lua_register_general() {
luabind::def("log", (void(*)(int, std::string))&lua_log),
luabind::def("debug", (void(*)(std::string))&lua_debug),
luabind::def("debug", (void(*)(std::string, int))&lua_debug),
luabind::def("log_combat", (void(*)(std::string))&lua_log_combat)
luabind::def("log_combat", (void(*)(std::string))&lua_log_combat),
/**
* Expansions
*/
luabind::def("is_classic_enabled", &lua_is_classic_enabled),
luabind::def("is_the_ruins_of_kunark_enabled", &lua_is_the_ruins_of_kunark_enabled),
luabind::def("is_the_scars_of_velious_enabled", &lua_is_the_scars_of_velious_enabled),
luabind::def("is_the_shadows_of_luclin_enabled", &lua_is_the_shadows_of_luclin_enabled),
luabind::def("is_the_planes_of_power_enabled", &lua_is_the_planes_of_power_enabled),
luabind::def("is_the_legacy_of_ykesha_enabled", &lua_is_the_legacy_of_ykesha_enabled),
luabind::def("is_lost_dungeons_of_norrath_enabled", &lua_is_lost_dungeons_of_norrath_enabled),
luabind::def("is_gates_of_discord_enabled", &lua_is_gates_of_discord_enabled),
luabind::def("is_omens_of_war_enabled", &lua_is_omens_of_war_enabled),
luabind::def("is_dragons_of_norrath_enabled", &lua_is_dragons_of_norrath_enabled),
luabind::def("is_depths_of_darkhollow_enabled", &lua_is_depths_of_darkhollow_enabled),
luabind::def("is_prophecy_of_ro_enabled", &lua_is_prophecy_of_ro_enabled),
luabind::def("is_the_serpents_spine_enabled", &lua_is_the_serpents_spine_enabled),
luabind::def("is_the_buried_sea_enabled", &lua_is_the_buried_sea_enabled),
luabind::def("is_secrets_of_faydwer_enabled", &lua_is_secrets_of_faydwer_enabled),
luabind::def("is_seeds_of_destruction_enabled", &lua_is_seeds_of_destruction_enabled),
luabind::def("is_underfoot_enabled", &lua_is_underfoot_enabled),
luabind::def("is_house_of_thule_enabled", &lua_is_house_of_thule_enabled),
luabind::def("is_veil_of_alaris_enabled", &lua_is_veil_of_alaris_enabled),
luabind::def("is_rain_of_fear_enabled", &lua_is_rain_of_fear_enabled),
luabind::def("is_call_of_the_forsaken_enabled", &lua_is_call_of_the_forsaken_enabled),
luabind::def("is_the_darkend_sea_enabled", &lua_is_the_darkend_sea_enabled),
luabind::def("is_the_broken_mirror_enabled", &lua_is_the_broken_mirror_enabled),
luabind::def("is_empires_of_kunark_enabled", &lua_is_empires_of_kunark_enabled),
luabind::def("is_ring_of_scale_enabled", &lua_is_ring_of_scale_enabled),
luabind::def("is_the_burning_lands_enabled", &lua_is_the_burning_lands_enabled),
luabind::def("is_torment_of_velious_enabled", &lua_is_torment_of_velious_enabled),
luabind::def("is_current_expansion_classic", &lua_is_current_expansion_classic),
luabind::def("is_current_expansion_the_ruins_of_kunark", &lua_is_current_expansion_the_ruins_of_kunark),
luabind::def("is_current_expansion_the_scars_of_velious", &lua_is_current_expansion_the_scars_of_velious),
luabind::def("is_current_expansion_the_shadows_of_luclin", &lua_is_current_expansion_the_shadows_of_luclin),
luabind::def("is_current_expansion_the_planes_of_power", &lua_is_current_expansion_the_planes_of_power),
luabind::def("is_current_expansion_the_legacy_of_ykesha", &lua_is_current_expansion_the_legacy_of_ykesha),
luabind::def("is_current_expansion_lost_dungeons_of_norrath", &lua_is_current_expansion_lost_dungeons_of_norrath),
luabind::def("is_current_expansion_gates_of_discord", &lua_is_current_expansion_gates_of_discord),
luabind::def("is_current_expansion_omens_of_war", &lua_is_current_expansion_omens_of_war),
luabind::def("is_current_expansion_dragons_of_norrath", &lua_is_current_expansion_dragons_of_norrath),
luabind::def("is_current_expansion_depths_of_darkhollow", &lua_is_current_expansion_depths_of_darkhollow),
luabind::def("is_current_expansion_prophecy_of_ro", &lua_is_current_expansion_prophecy_of_ro),
luabind::def("is_current_expansion_the_serpents_spine", &lua_is_current_expansion_the_serpents_spine),
luabind::def("is_current_expansion_the_buried_sea", &lua_is_current_expansion_the_buried_sea),
luabind::def("is_current_expansion_secrets_of_faydwer", &lua_is_current_expansion_secrets_of_faydwer),
luabind::def("is_current_expansion_seeds_of_destruction", &lua_is_current_expansion_seeds_of_destruction),
luabind::def("is_current_expansion_underfoot", &lua_is_current_expansion_underfoot),
luabind::def("is_current_expansion_house_of_thule", &lua_is_current_expansion_house_of_thule),
luabind::def("is_current_expansion_veil_of_alaris", &lua_is_current_expansion_veil_of_alaris),
luabind::def("is_current_expansion_rain_of_fear", &lua_is_current_expansion_rain_of_fear),
luabind::def("is_current_expansion_call_of_the_forsaken", &lua_is_current_expansion_call_of_the_forsaken),
luabind::def("is_current_expansion_the_darkend_sea", &lua_is_current_expansion_the_darkend_sea),
luabind::def("is_current_expansion_the_broken_mirror", &lua_is_current_expansion_the_broken_mirror),
luabind::def("is_current_expansion_empires_of_kunark", &lua_is_current_expansion_empires_of_kunark),
luabind::def("is_current_expansion_ring_of_scale", &lua_is_current_expansion_ring_of_scale),
luabind::def("is_current_expansion_the_burning_lands", &lua_is_current_expansion_the_burning_lands),
luabind::def("is_current_expansion_torment_of_velious", &lua_is_current_expansion_torment_of_velious),
/**
* Content flags
*/
luabind::def("is_content_flag_enabled", (bool(*)(std::string))&lua_is_content_flag_enabled),
luabind::def("set_content_flag", (void(*)(std::string, bool))&lua_set_content_flag)
];
}
+60 -24
View File
@@ -1,20 +1,22 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#define DONT_SHARED_OPCODES
#define PLATFORM_ZONE 1
@@ -53,6 +55,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#ifdef BOTS
#include "bot_command.h"
#endif
#include "zonedb.h"
#include "zone_store.h"
#include "zone_config.h"
#include "titles.h"
#include "guild_mgr.h"
@@ -67,6 +71,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/event/timer.h"
#include "../common/net/eqstream.h"
#include "../common/net/servertalk_server.h"
#include "../common/content/world_content_service.h"
#include "../common/repositories/content_flags_repository.h"
#include <iostream>
#include <string>
@@ -90,8 +96,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#else
#include <pthread.h>
#include "../common/unix.h"
#include "zone_store.h"
#endif
volatile bool RunLoops = true;
#ifdef __FreeBSD__
#include <pthread_np.h>
#endif
@@ -100,6 +109,7 @@ extern volatile bool is_zone_loaded;
EntityList entity_list;
WorldServer worldserver;
ZoneStore zone_store;
uint32 numclients = 0;
char errorname[32];
extern Zone* zone;
@@ -110,6 +120,7 @@ TaskManager *taskmanager = 0;
NpcScaleManager *npc_scale_manager;
QuestParserCollection *parse = 0;
EQEmuLogSys LogSys;
WorldContentService content_service;
const SPDat_Spell_Struct* spells;
int32 SPDAT_RECORDS = -1;
const ZoneConfig *Config;
@@ -240,6 +251,25 @@ int main(int argc, char** argv) {
return 1;
}
/**
* Multi-tenancy: Content Database
*/
if (!Config->ContentDbHost.empty()) {
if (!content_db.Connect(
Config->ContentDbHost.c_str() ,
Config->ContentDbUsername.c_str(),
Config->ContentDbPassword.c_str(),
Config->ContentDbName.c_str(),
Config->ContentDbPort,
"content"
)) {
LogError("Cannot continue without a content database connection");
return 1;
}
} else {
content_db.SetMysql(database.getMySQL());
}
/* Register Log System and Settings */
LogSys.SetGMSayHandler(&Zone::GMSayHookCallBackProcess);
database.LoadLogSettings(LogSys.log_settings);
@@ -293,7 +323,8 @@ int main(int argc, char** argv) {
}
LogInfo("Loading zone names");
database.LoadZoneNames();
zone_store.LoadZones();
LogInfo("Loading items");
if (!database.LoadItems(hotfix_name)) {
@@ -302,7 +333,7 @@ int main(int argc, char** argv) {
}
LogInfo("Loading npc faction lists");
if (!database.LoadNPCFactionLists(hotfix_name)) {
if (!content_db.LoadNPCFactionLists(hotfix_name)) {
LogError("Loading npcs faction lists failed!");
return 1;
}
@@ -333,13 +364,13 @@ int main(int argc, char** argv) {
guild_mgr.LoadGuilds();
LogInfo("Loading factions");
database.LoadFactionData();
content_db.LoadFactionData();
LogInfo("Loading titles");
title_manager.LoadTitles();
LogInfo("Loading tributes");
database.LoadTributes();
content_db.LoadTributes();
LogInfo("Loading corpse timers");
database.GetDecayTimes(npcCorpseDecayTimes);
@@ -350,7 +381,7 @@ int main(int argc, char** argv) {
LogInfo("Loading commands");
int retval = command_init();
if (retval<0)
if (retval < 0)
LogError("Command loading failed");
else
LogInfo("{} commands loaded", retval);
@@ -377,6 +408,10 @@ int main(int argc, char** argv) {
LogInfo("Initialized dynamic dictionary entries");
}
content_service.SetExpansionContext();
ZoneStore::LoadContentFlags();
#ifdef BOTS
LogInfo("Loading bot commands");
int botretval = bot_command_init();
@@ -426,9 +461,9 @@ int main(int argc, char** argv) {
if (!strlen(zone_name) || !strcmp(zone_name, ".")) {
LogInfo("Entering sleep mode");
}
else if (!Zone::Bootup(database.GetZoneID(zone_name), instance_id, true)) {
else if (!Zone::Bootup(ZoneID(zone_name), instance_id, true)) {
LogError("Zone Bootup failed :: Zone::Bootup");
zone = 0;
zone = nullptr;
}
//register all the patches we have avaliable with the stream identifier.
@@ -548,6 +583,7 @@ int main(int argc, char** argv) {
if (InterserverTimer.Check()) {
InterserverTimer.Start();
database.ping();
content_db.ping();
entity_list.UpdateWho();
}
};
+2 -2
View File
@@ -4757,7 +4757,7 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id,
if(merc_template)
{
//TODO: Maybe add a way of updating client merc stats in a seperate function? like, for example, on leveling up.
const NPCType* npc_type_to_copy = database.GetMercType(merc_template->MercNPCID, merc_template->RaceID, c->GetLevel());
const NPCType* npc_type_to_copy = content_db.GetMercType(merc_template->MercNPCID, merc_template->RaceID, c->GetLevel());
if(npc_type_to_copy != nullptr)
{
//This is actually a very terrible method of assigning stats, and should be changed at some point. See the comment in merc's deconstructor.
@@ -4886,7 +4886,7 @@ void Merc::UpdateMercStats(Client *c, bool setmax)
if (c->GetMercInfo().MercTemplateID > 0) {
Log(Logs::General, Logs::Mercenaries, "Updating Mercenary Stats for %s (%s).", GetName(),
c->GetName());
const NPCType *npc_type = database.GetMercType(
const NPCType *npc_type = content_db.GetMercType(
zone->GetMercTemplate(c->GetMercInfo().MercTemplateID)->MercNPCID, GetRace(), c->GetLevel());
if (npc_type) {
max_hp = npc_type->max_hp;
+9 -5
View File
@@ -1831,7 +1831,11 @@ void NPC::AI_SetupNextWaypoint() {
}
else {
pause_timer_complete = false;
LogPathing("We are departing waypoint [{}]", cur_wp);
LogPathingDetail(
"[{}] departing waypoint [{}]",
GetCleanName(),
cur_wp
);
//if we were under quest control (with no grid), we are done now..
if (cur_wp == EQ::WaypointStatus::QuestControlNoGrid) {
LogPathing("Non-grid quest mob has reached its quest ordered waypoint. Leaving pathing mode");
@@ -2474,12 +2478,12 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) {
AIautocastspell_timer->Disable();
return false;
}
DBnpcspells_Struct* spell_list = database.GetNPCSpells(iDBSpellsID);
DBnpcspells_Struct* spell_list = content_db.GetNPCSpells(iDBSpellsID);
if (!spell_list) {
AIautocastspell_timer->Disable();
return false;
}
DBnpcspells_Struct* parentlist = database.GetNPCSpells(spell_list->parent_list);
DBnpcspells_Struct* parentlist = content_db.GetNPCSpells(spell_list->parent_list);
#if MobAI_DEBUG_Spells >= 10
std::string debug_msg = StringFormat("Loading NPCSpells onto %s: dbspellsid=%u, level=%u", this->GetName(), iDBSpellsID, this->GetLevel());
if (spell_list) {
@@ -2646,13 +2650,13 @@ bool NPC::AI_AddNPCSpellsEffects(uint32 iDBSpellsEffectsID) {
if (iDBSpellsEffectsID == 0)
return false;
DBnpcspellseffects_Struct* spell_effects_list = database.GetNPCSpellsEffects(iDBSpellsEffectsID);
DBnpcspellseffects_Struct* spell_effects_list = content_db.GetNPCSpellsEffects(iDBSpellsEffectsID);
if (!spell_effects_list) {
return false;
}
DBnpcspellseffects_Struct* parentlist = database.GetNPCSpellsEffects(spell_effects_list->parent_list);
DBnpcspellseffects_Struct* parentlist = content_db.GetNPCSpellsEffects(spell_effects_list->parent_list);
uint32 i;
#if MobAI_DEBUG_Spells >= 10
+2 -1
View File
@@ -27,6 +27,7 @@
#include "mob.h"
#include "quest_parser_collection.h"
#include "zonedb.h"
#include "zone_store.h"
#ifdef BOTS
#include "bot.h"
@@ -545,4 +546,4 @@ void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 h
entity_list.QueueClients(this, outapp);
safe_delete(outapp);
}
}
+1
View File
@@ -8,6 +8,7 @@
#include "zone.h"
#include "spawngroup.h"
#include "zonedb.h"
#include "zone_store.h"
#include "npc.h"
#include "mob.h"
#include "client.h"
+2 -2
View File
@@ -1976,7 +1976,7 @@ void Mob::NPCSpecialAttacks(const char* parse, int permtag, bool reset, bool rem
if(permtag == 1 && this->GetNPCTypeID() > 0)
{
if(database.SetSpecialAttkFlag(this->GetNPCTypeID(), orig_parse))
if(content_db.SetSpecialAttkFlag(this->GetNPCTypeID(), orig_parse))
{
LogInfo("NPCTypeID: [{}] flagged to [{}] for Special Attacks.\n",this->GetNPCTypeID(),orig_parse);
}
@@ -3211,7 +3211,7 @@ void NPC::AIYellForHelp(Mob *sender, Mob *attacker)
if (mob->GetLevel() >= 50 || attacker->GetLevelCon(mob->GetLevel()) != CON_GRAY) {
bool use_primary_faction = false;
if (mob->GetPrimaryFaction() == sender->CastToNPC()->GetPrimaryFaction()) {
const NPCFactionList *cf = database.GetNPCFactionEntry(mob->CastToNPC()->GetNPCFactionID());
const NPCFactionList *cf = content_db.GetNPCFactionEntry(mob->CastToNPC()->GetNPCFactionID());
if (cf) {
if (cf->assistprimaryfaction != 0) {
use_primary_faction = true;
+4 -3
View File
@@ -23,6 +23,7 @@
#include "mob.h"
#include "qglobals.h"
#include "zonedb.h"
#include "zone_store.h"
#include "zonedump.h"
#include <deque>
@@ -269,7 +270,7 @@ public:
void SetNPCFactionID(int32 in)
{
npc_faction_id = in;
database.GetFactionIdsForNPC(npc_faction_id, &faction_list, &primary_faction);
content_db.GetFactionIdsForNPC(npc_faction_id, &faction_list, &primary_faction);
}
glm::vec4 m_SpawnPoint;
@@ -303,7 +304,7 @@ public:
int GetMaxWp() const { return max_wp; }
void DisplayWaypointInfo(Client *to);
void CalculateNewWaypoint();
void AssignWaypoints(int32 grid, int start_wp = 0);
void AssignWaypoints(int32 grid_id, int start_wp = 0);
void SetWaypointPause();
void UpdateWaypoint(int wp_index);
@@ -512,7 +513,7 @@ protected:
uint32 npc_spells_id;
uint8 casting_spell_AIindex;
uint32* pDontCastBefore_casting_spell;
std::vector<AISpells_Struct> AIspells;
bool HasAISpell;
+3 -3
View File
@@ -166,7 +166,7 @@ void NpcScaleManager::ScaleNPC(NPC *npc)
bool NpcScaleManager::LoadScaleData()
{
auto results = database.QueryDatabase(
auto results = content_db.QueryDatabase(
"SELECT "
"type,"
"level,"
@@ -550,7 +550,7 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCStatically(NPC *&npc)
npc->GetNPCTypeID()
);
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
return results.Success();
}
@@ -610,7 +610,7 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCDynamically(NPC *&npc)
npc->GetNPCTypeID()
);
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
return results.Success();
}
+61 -44
View File
@@ -26,6 +26,8 @@
#include "quest_parser_collection.h"
#include "zonedb.h"
#include "zone_store.h"
#include "../common/repositories/criteria/content_filter_criteria.h"
#include <iostream>
@@ -292,11 +294,11 @@ bool Object::Save()
{
if (m_id) {
// Update existing
database.UpdateObject(m_id, m_type, m_icon, m_data, m_inst);
content_db.UpdateObject(m_id, m_type, m_icon, m_data, m_inst);
}
else {
// Doesn't yet exist, add now
m_id = database.AddObject(m_type, m_icon, m_data, m_inst);
m_id = content_db.AddObject(m_type, m_icon, m_data, m_inst);
}
return true;
@@ -306,11 +308,11 @@ uint16 Object::VarSave()
{
if (m_id) {
// Update existing
database.UpdateObject(m_id, m_type, m_icon, m_data, m_inst);
content_db.UpdateObject(m_id, m_type, m_icon, m_data, m_inst);
}
else {
// Doesn't yet exist, add now
m_id = database.AddObject(m_type, m_icon, m_data, m_inst);
m_id = content_db.AddObject(m_type, m_icon, m_data, m_inst);
}
return m_id;
}
@@ -319,7 +321,7 @@ uint16 Object::VarSave()
void Object::Delete(bool reset_state)
{
if (m_id != 0) {
database.DeleteObject(m_id);
content_db.DeleteObject(m_id);
}
if (reset_state) {
@@ -436,7 +438,7 @@ bool Object::Process(){
safe_delete(outapp);
// Remove object
database.DeleteObject(m_id);
content_db.DeleteObject(m_id);
return false;
}
@@ -460,7 +462,7 @@ void Object::RandomSpawn(bool send_packet) {
m_data.x = zone->random.Real(m_min_x, m_max_x);
m_data.y = zone->random.Real(m_min_y, m_max_y);
if(m_data.z == BEST_Z_INVALID) {
glm::vec3 me;
me.x = m_data.x;
@@ -470,11 +472,11 @@ void Object::RandomSpawn(bool send_packet) {
float best_z = zone->zonemap->FindClosestZ(me, &hit);
if (best_z != BEST_Z_INVALID) {
m_data.z = best_z + 0.1f;
}
}
}
LogInfo("Object::RandomSpawn([{}]): [{}] ([{}], [{}], [{}])", m_data.object_name, m_inst->GetID(), m_data.x, m_data.y, m_data.z);
respawn_timer.Disable();
if(send_packet) {
@@ -520,7 +522,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
co->drop_id = 0;
entity_list.QueueClients(nullptr, outapp, false);
safe_delete(outapp);
// No longer using a tradeskill object
sender->SetTradeskillObject(nullptr);
user = nullptr;
@@ -553,7 +555,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
safe_delete(outapp);
// Remove object
database.DeleteObject(m_id);
content_db.DeleteObject(m_id);
if(!m_ground_spawn)
entity_list.RemoveEntity(this->GetID());
} else {
@@ -651,9 +653,10 @@ uint32 ZoneDatabase::AddObject(uint32 type, uint32 icon, const Object_Struct& ob
return 0;
}
// Save container contents, if container
if (inst && inst->IsType(EQ::item::ItemClassBag))
SaveWorldContainer(object.zone_id, database_id, inst);
// Save container contents, if container
if (inst && inst->IsType(EQ::item::ItemClassBag)) {
SaveWorldContainer(object.zone_id, database_id, inst);
}
return database_id;
}
@@ -669,42 +672,53 @@ void ZoneDatabase::UpdateObject(uint32 id, uint32 type, uint32 icon, const Objec
charges = inst->GetCharges();
}
// SQL Escape object_name
uint32 len = strlen(object.object_name) * 2 + 1;
auto object_name = new char[len];
DoEscapeString(object_name, object.object_name, strlen(object.object_name));
if (inst && !inst->IsType(EQ::item::ItemClassBag)) {
uint32 len = strlen(object.object_name) * 2 + 1;
auto object_name = new char[len];
DoEscapeString(object_name, object.object_name, strlen(object.object_name));
// Save new record for object
std::string query = StringFormat("UPDATE object SET "
"zoneid = %i, xpos = %f, ypos = %f, zpos = %f, heading = %f, "
"itemid = %i, charges = %i, objectname = '%s', type = %i, icon = %i, "
"size = %f, tilt_x = %f, tilt_y = %f "
"WHERE id = %i",
object.zone_id, object.x, object.y, object.z, object.heading,
item_id, charges, object_name, type, icon,
object.size, object.tilt_x, object.tilt_y, id);
safe_delete_array(object_name);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogError("Unable to update object: [{}]", results.ErrorMessage().c_str());
return;
// Save new record for object
std::string query = StringFormat(
"UPDATE object SET "
"zoneid = %i, xpos = %f, ypos = %f, zpos = %f, heading = %f, "
"itemid = %i, charges = %i, objectname = '%s', type = %i, icon = %i, "
"size = %f, tilt_x = %f, tilt_y = %f "
"WHERE id = %i",
object.zone_id, object.x, object.y, object.z, object.heading,
item_id, charges, object_name, type, icon,
object.size, object.tilt_x, object.tilt_y, id
);
safe_delete_array(object_name);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogError("Unable to update object: [{}]", results.ErrorMessage().c_str());
return;
}
}
// Save container contents, if container
if (inst && inst->IsType(EQ::item::ItemClassBag))
SaveWorldContainer(object.zone_id, id, inst);
// Save container contents, if container
if (inst && inst->IsType(EQ::item::ItemClassBag)) {
SaveWorldContainer(object.zone_id, id, inst);
}
}
//
Ground_Spawns* ZoneDatabase::LoadGroundSpawns(uint32 zone_id, int16 version, Ground_Spawns* gs) {
std::string query = StringFormat("SELECT max_x, max_y, max_z, "
"min_x, min_y, heading, name, "
"item, max_allowed, respawn_timer "
"FROM ground_spawns "
"WHERE zoneid = %i AND (version = %u OR version = -1) "
"LIMIT 50", zone_id, version);
auto results = QueryDatabase(query);
if (!results.Success()) {
std::string query = StringFormat(
"SELECT max_x, max_y, max_z, "
"min_x, min_y, heading, name, "
"item, max_allowed, respawn_timer "
"FROM ground_spawns "
"WHERE zoneid = %i AND (version = %u OR version = -1) %s "
"LIMIT 50",
zone_id,
version,
ContentFilterCriteria::apply().c_str()
);
auto results = QueryDatabase(query);
if (!results.Success()) {
return gs;
}
@@ -726,7 +740,10 @@ Ground_Spawns* ZoneDatabase::LoadGroundSpawns(uint32 zone_id, int16 version, Gro
void ZoneDatabase::DeleteObject(uint32 id)
{
// delete record of object
if (id == 0) {
return;
}
std::string query = StringFormat("DELETE FROM object WHERE id = %i", id);
auto results = QueryDatabase(query);
if (!results.Success()) {
+1
View File
@@ -25,6 +25,7 @@
#include "client.h"
#include "zonedb.h"
#include "zone_store.h"
class Client;
+8 -7
View File
@@ -27,6 +27,7 @@
#include "pets.h"
#include "zonedb.h"
#include "zone_store.h"
#include <string>
@@ -211,14 +212,14 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
//lookup our pets table record for this type
PetRecord record;
if(!database.GetPoweredPetEntry(pettype, act_power, &record)) {
if(!content_db.GetPoweredPetEntry(pettype, act_power, &record)) {
Message(Chat::Red, "Unable to find data for pet %s", pettype);
LogError("Unable to find data for pet [{}], check pets table", pettype);
return;
}
//find the NPC data for the specified NPC type
const NPCType *base = database.LoadNPCTypesData(record.npc_type);
const NPCType *base = content_db.LoadNPCTypesData(record.npc_type);
if(base == nullptr) {
Message(Chat::Red, "Unable to load NPC data for pet %s", pettype);
LogError("Unable to load NPC data for pet [{}] (NPC ID [{}]), check pets and npc_types tables", pettype, record.npc_type);
@@ -230,7 +231,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
memcpy(npc_type, base, sizeof(NPCType));
// If pet power is set to -1 in the DB, use stat scaling
if ((this->IsClient()
if ((this->IsClient()
#ifdef BOTS
|| this->IsBot()
#endif
@@ -348,7 +349,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
"130, 139, 141, 183, 236, 237, 238, 239, 254, 266, 329, 330, 378, 379, "
"380, 381, 382, 383, 404, 522) "
"ORDER BY RAND() LIMIT 1", zone->GetShortName());
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
safe_delete(npc_type);
return;
@@ -364,7 +365,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
monsterid = 567;
// give the summoned pet the attributes of the monster we found
const NPCType* monster = database.LoadNPCTypesData(monsterid);
const NPCType* monster = content_db.LoadNPCTypesData(monsterid);
if(monster) {
npc_type->race = monster->race;
npc_type->size = monster->size;
@@ -389,7 +390,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
memset(petinv, 0, sizeof(petinv));
const EQ::ItemData *item = nullptr;
if (database.GetBasePetItems(record.equipmentset, petinv)) {
if (content_db.GetBasePetItems(record.equipmentset, petinv)) {
for (int i = EQ::invslot::EQUIPMENT_BEGIN; i <= EQ::invslot::EQUIPMENT_END; i++)
if (petinv[i]) {
item = database.GetItem(petinv[i]);
@@ -620,7 +621,7 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) {
if (item2) {
bool noDrop=(item2->NoDrop == 0); // Field is reverse logic
bool petCanHaveNoDrop = (RuleB(Pets, CanTakeNoDrop) &&
bool petCanHaveNoDrop = (RuleB(Pets, CanTakeNoDrop) &&
_CLIENTPET(this) && GetPetType() <= petOther);
if (!noDrop || petCanHaveNoDrop) {
+1
View File
@@ -19,6 +19,7 @@
#define __QUEST_H__
#include "zonedb.h"
#include "zone_store.h"
typedef struct _tag_quest_entry{
char *m_pQuestName;
+1 -1
View File
@@ -488,7 +488,7 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string
}
//second look for /quests/zone/npcname.ext (precedence)
const NPCType *npc_type = database.LoadNPCTypesData(npcid);
const NPCType *npc_type = content_db.LoadNPCTypesData(npcid);
if (!npc_type && npcid != ZONE_CONTROLLER_NPC_ID) {
return nullptr;
}
+26 -25
View File
@@ -35,6 +35,7 @@
#include "worldserver.h"
#include "zone.h"
#include "zonedb.h"
#include "zone_store.h"
#include <iostream>
#include <limits.h>
@@ -193,7 +194,7 @@ void QuestManager::write(const char *file, const char *str) {
Mob* QuestManager::spawn2(int npc_type, int grid, int unused, const glm::vec4& position) {
const NPCType* tmp = 0;
if (tmp = database.LoadNPCTypesData(npc_type))
if (tmp = content_db.LoadNPCTypesData(npc_type))
{
auto npc = new NPC(tmp, nullptr, position, GravityBehavior::Water);
npc->AddLootTable();
@@ -217,7 +218,7 @@ Mob* QuestManager::unique_spawn(int npc_type, int grid, int unused, const glm::v
}
const NPCType* tmp = 0;
if (tmp = database.LoadNPCTypesData(npc_type))
if (tmp = content_db.LoadNPCTypesData(npc_type))
{
auto npc = new NPC(tmp, nullptr, position, GravityBehavior::Water);
npc->AddLootTable();
@@ -252,7 +253,7 @@ Mob *QuestManager::spawn_from_spawn2(uint32 spawn2_id)
if (found_spawn) {
SpawnGroup *spawn_group = zone->spawn_group_list.GetSpawnGroup(found_spawn->SpawnGroupID());
if (!spawn_group) {
database.LoadSpawnGroupsByID(found_spawn->SpawnGroupID(), &zone->spawn_group_list);
content_db.LoadSpawnGroupsByID(found_spawn->SpawnGroupID(), &zone->spawn_group_list);
spawn_group = zone->spawn_group_list.GetSpawnGroup(found_spawn->SpawnGroupID());
if (!spawn_group) {
return nullptr;
@@ -272,7 +273,7 @@ Mob *QuestManager::spawn_from_spawn2(uint32 spawn2_id)
return nullptr;
}
const NPCType *tmp = database.LoadNPCTypesData(npcid);
const NPCType *tmp = content_db.LoadNPCTypesData(npcid);
if (!tmp) {
return nullptr;
}
@@ -397,7 +398,7 @@ void QuestManager::Zone(const char *zone_name) {
ztz->response = 0;
ztz->current_zone_id = zone->GetZoneID();
ztz->current_instance_id = zone->GetInstanceID();
ztz->requested_zone_id = database.GetZoneID(zone_name);
ztz->requested_zone_id = ZoneID(zone_name);
ztz->admin = initiator->Admin();
strcpy(ztz->name, initiator->GetName());
ztz->guild_id = initiator->GuildID();
@@ -416,7 +417,7 @@ void QuestManager::ZoneGroup(const char *zone_name) {
ztz->response = 0;
ztz->current_zone_id = zone->GetZoneID();
ztz->current_instance_id = zone->GetInstanceID();
ztz->requested_zone_id = database.GetZoneID(zone_name);
ztz->requested_zone_id = ZoneID(zone_name);
ztz->admin = initiator->Admin();
strcpy(ztz->name, initiator->GetName());
ztz->guild_id = initiator->GuildID();
@@ -433,7 +434,7 @@ void QuestManager::ZoneGroup(const char *zone_name) {
ztz->response = 0;
ztz->current_zone_id = zone->GetZoneID();
ztz->current_instance_id = zone->GetInstanceID();
ztz->requested_zone_id = database.GetZoneID(zone_name);
ztz->requested_zone_id = ZoneID(zone_name);
ztz->admin = group_member->Admin();
strcpy(ztz->name, group_member->GetName());
ztz->guild_id = group_member->GuildID();
@@ -455,7 +456,7 @@ void QuestManager::ZoneRaid(const char *zone_name) {
ztz->response = 0;
ztz->current_zone_id = zone->GetZoneID();
ztz->current_instance_id = zone->GetInstanceID();
ztz->requested_zone_id = database.GetZoneID(zone_name);
ztz->requested_zone_id = ZoneID(zone_name);
ztz->admin = initiator->Admin();
strcpy(ztz->name, initiator->GetName());
ztz->guild_id = initiator->GuildID();
@@ -472,7 +473,7 @@ void QuestManager::ZoneRaid(const char *zone_name) {
ztz->response = 0;
ztz->current_zone_id = zone->GetZoneID();
ztz->current_instance_id = zone->GetInstanceID();
ztz->requested_zone_id = database.GetZoneID(zone_name);
ztz->requested_zone_id = ZoneID(zone_name);
ztz->admin = raid_member->Admin();
strcpy(ztz->name, raid_member->GetName());
ztz->guild_id = raid_member->GuildID();
@@ -717,9 +718,9 @@ void QuestManager::resumetimer(const char *timer_name) {
bool QuestManager::ispausedtimer(const char *timer_name) {
QuestManagerCurrentQuestVars();
std::list<PausedTimer>::iterator pcur = PTimerList.begin(), pend;
pend = PTimerList.end();
while (pcur != pend)
{
@@ -1095,7 +1096,7 @@ uint16 QuestManager::scribespells(uint8 max_level, uint8 min_level) {
((spell_id >= 0 && spell_id < SPDAT_RECORDS) ? spells[spell_id].name : "Out-of-range"),
spell_id
);
break;
}
if (spell_id < 0 || spell_id >= SPDAT_RECORDS) {
@@ -1861,7 +1862,7 @@ void QuestManager::respawn(int npcTypeID, int grid) {
quests_running_.push(e);
const NPCType* npcType = nullptr;
if ((npcType = database.LoadNPCTypesData(npcTypeID)))
if ((npcType = content_db.LoadNPCTypesData(npcTypeID)))
{
owner = new NPC(npcType, nullptr, owner->GetPosition(), GravityBehavior::Water);
owner->CastToNPC()->AddLootTable();
@@ -1935,7 +1936,7 @@ void QuestManager::showgrid(int grid) {
std::string query = StringFormat("SELECT `x`,`y`,`z` FROM grid_entries "
"WHERE `gridid` = %i AND `zoneid` = %i "
"ORDER BY `number`", grid, zone->GetZoneID());
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
LogQuests("Error loading grid [{}] for showgrid(): [{}]", grid, results.ErrorMessage().c_str());
return;
@@ -2018,7 +2019,7 @@ int QuestManager::getplayercorpsecount(uint32 char_id) {
return database.CountCharacterCorpses(char_id);
}
return 0;
}
int QuestManager::getplayercorpsecountbyzoneid(uint32 char_id, uint32 zone_id) {
@@ -2706,7 +2707,7 @@ int QuestManager::countitem(uint32 item_id) {
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
};
const size_t size = sizeof(slots) / sizeof(slots[0]);
const size_t size = sizeof(slots) / sizeof(slots[0]);
for (int slot_index = 0; slot_index < size; ++slot_index) {
for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) {
item = initiator->GetInv().GetItem(slot_id);
@@ -2831,7 +2832,7 @@ uint16 QuestManager::CreateInstance(const char *zone, int16 version, uint32 dura
QuestManagerCurrentQuestVars();
if(initiator)
{
uint32 zone_id = database.GetZoneID(zone);
uint32 zone_id = ZoneID(zone);
if(zone_id == 0)
return 0;
@@ -2884,10 +2885,10 @@ uint32 QuestManager::GetInstanceTimer() {
uint32 QuestManager::GetInstanceTimerByID(uint16 instance_id) {
if (instance_id == 0)
return 0;
std::string query = StringFormat("SELECT ((start_time + duration) - UNIX_TIMESTAMP()) AS `remaining` FROM `instance_list` WHERE `id` = %lu", (unsigned long)instance_id);
auto results = database.QueryDatabase(query);
if (results.Success()) {
auto row = results.begin();
uint32 timer = atoi(row[0]);
@@ -2901,13 +2902,13 @@ uint16 QuestManager::GetInstanceID(const char *zone, int16 version)
QuestManagerCurrentQuestVars();
if (initiator)
{
return database.GetInstanceID(zone, initiator->CharacterID(), version);
return database.GetInstanceID(ZoneID(zone), initiator->CharacterID(), version);
}
return 0;
}
uint16 QuestManager::GetInstanceIDByCharID(const char *zone, int16 version, uint32 char_id) {
return database.GetInstanceID(zone, char_id, version);
return database.GetInstanceID(ZoneID(zone), char_id, version);
}
void QuestManager::AssignToInstance(uint16 instance_id)
@@ -3259,12 +3260,12 @@ uint16 QuestManager::CreateDoor(const char* model, float x, float y, float z, fl
}
int32 QuestManager::GetZoneID(const char *zone) {
return static_cast<int32>(database.GetZoneID(zone));
return static_cast<int32>(ZoneID(zone));
}
const char* QuestManager::GetZoneLongName(const char *zone) {
char *long_name;
database.GetZoneLongName(zone, &long_name);
content_db.GetZoneLongName(zone, &long_name);
std::string ln = long_name;
safe_delete_array(long_name);
@@ -4141,7 +4142,7 @@ bool QuestManager::EnableRecipe(uint32 recipe_id)
{
bool success = false;
if (recipe_id > 0)
success = database.EnableRecipe(recipe_id);
success = content_db.EnableRecipe(recipe_id);
return (success);
}
@@ -4149,7 +4150,7 @@ bool QuestManager::DisableRecipe(uint32 recipe_id)
{
bool success = false;
if (recipe_id > 0)
success = database.DisableRecipe(recipe_id);
success = content_db.DisableRecipe(recipe_id);
return (success);
}
+21 -17
View File
@@ -26,6 +26,7 @@
#include "worldserver.h"
#include "zone.h"
#include "zonedb.h"
#include "zone_store.h"
extern EntityList entity_list;
extern Zone* zone;
@@ -165,8 +166,11 @@ bool Spawn2::Process() {
return (true);
}
if (spawn_group == nullptr) {
database.LoadSpawnGroupsByID(spawngroup_id_, &zone->spawn_group_list);
/**
* Wait for init grids timer because we bulk load this data before trying to fetch it individually
*/
if (spawn_group == nullptr && zone->GetInitgridsTimer().Check()) {
content_db.LoadSpawnGroupsByID(spawngroup_id_, &zone->spawn_group_list);
spawn_group = zone->spawn_group_list.GetSpawnGroup(spawngroup_id_);
}
@@ -192,7 +196,7 @@ bool Spawn2::Process() {
}
//try to find our NPC type.
const NPCType *tmp = database.LoadNPCTypesData(npcid);
const NPCType *tmp = content_db.LoadNPCTypesData(npcid);
if (tmp == nullptr) {
LogSpawns("Spawn2 [{}]: Spawn group [{}] yeilded an invalid NPC type [{}]", spawn2_id, spawngroup_id_, npcid);
Reset(); //try again later
@@ -239,7 +243,7 @@ bool Spawn2::Process() {
if (spawn_group->wp_spawns && grid_ > 0)
{
glm::vec4 wploc;
starting_wp = database.GetRandomWaypointLocFromGrid(wploc, zone->GetZoneID(), grid_);
starting_wp = content_db.GetRandomWaypointLocFromGrid(wploc, zone->GetZoneID(), grid_);
if (wploc.x != 0.0f || wploc.y != 0.0f || wploc.z != 0.0f)
{
loc = wploc;
@@ -431,7 +435,7 @@ bool ZoneDatabase::PopulateZoneSpawnListClose(uint32 zoneid, LinkedList<Spawn2*>
gettimeofday(&tv, nullptr);
/* Bulk Load NPC Types Data into the cache */
database.LoadNPCTypesData(0, true);
content_db.LoadNPCTypesData(0, true);
std::string spawn_query = StringFormat(
"SELECT "
@@ -458,7 +462,7 @@ bool ZoneDatabase::PopulateZoneSpawnListClose(uint32 zoneid, LinkedList<Spawn2*>
}
}
const char *zone_name = database.GetZoneName(zoneid);
const char *zone_name = ZoneName(zoneid);
std::string query = StringFormat(
"SELECT "
"id, "
@@ -480,7 +484,7 @@ bool ZoneDatabase::PopulateZoneSpawnListClose(uint32 zoneid, LinkedList<Spawn2*>
zone_name,
version
);
results = QueryDatabase(query);
results = database.QueryDatabase(query);
if (!results.Success()) {
return false;
@@ -504,7 +508,7 @@ bool ZoneDatabase::PopulateZoneSpawnListClose(uint32 zoneid, LinkedList<Spawn2*>
if (mob_distance > repop_distance)
continue;
new_spawn = new Spawn2( //
new_spawn = new Spawn2( //
atoi(row[0]), // uint32 in_spawn2_id
atoi(row[1]), // uint32 spawngroup_id
atof(row[2]), // float in_x
@@ -535,7 +539,7 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spa
gettimeofday(&tv, nullptr);
/* Bulk Load NPC Types Data into the cache */
database.LoadNPCTypesData(0, true);
content_db.LoadNPCTypesData(0, true);
std::string spawn_query = StringFormat(
"SELECT "
@@ -547,7 +551,7 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spa
"WHERE instance_id = %u",
zone->GetInstanceID()
);
auto results = QueryDatabase(spawn_query);
auto results = database.QueryDatabase(spawn_query);
for (auto row = results.begin(); row != results.end(); ++row) {
uint32 start_duration = atoi(row[1]) > 0 ? atoi(row[1]) : 0;
uint32 end_duration = atoi(row[2]) > 0 ? atoi(row[2]) : 0;
@@ -562,7 +566,7 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spa
}
}
const char *zone_name = database.GetZoneName(zoneid);
const char *zone_name = ZoneName(zoneid);
std::string query = StringFormat(
"SELECT "
"id, "
@@ -592,14 +596,14 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spa
for (auto row = results.begin(); row != results.end(); ++row) {
uint32 spawn_time_left = 0;
Spawn2* new_spawn = 0;
uint32 spawn_time_left = 0;
Spawn2* new_spawn = 0;
bool perl_enabled = atoi(row[11]) == 1 ? true : false;
if (spawn_times.count(atoi(row[0])) != 0)
spawn_time_left = spawn_times[atoi(row[0])];
new_spawn = new Spawn2( //
new_spawn = new Spawn2( //
atoi(row[0]), // uint32 in_spawn2_id
atoi(row[1]), // uint32 spawngroup_id
atof(row[2]), // float in_x
@@ -968,7 +972,7 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in
std::string query = StringFormat("SELECT id, onchange, value "
"FROM spawn_conditions "
"WHERE zone = '%s'", zone_name);
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
return false;
}
@@ -1214,7 +1218,7 @@ void SpawnConditionManager::SetCondition(const char *zone_short, uint32 instance
auto pack = new ServerPacket(ServerOP_SpawnCondition, sizeof(ServerSpawnCondition_Struct));
ServerSpawnCondition_Struct* ssc = (ServerSpawnCondition_Struct*)pack->pBuffer;
ssc->zoneID = database.GetZoneID(zone_short);
ssc->zoneID = ZoneID(zone_short);
ssc->instanceID = instance_id;
ssc->condition_id = condition_id;
ssc->value = new_value;
@@ -1346,7 +1350,7 @@ void SpawnConditionManager::ToggleEvent(uint32 event_id, bool enabled, bool stri
auto pack = new ServerPacket(ServerOP_SpawnEvent, sizeof(ServerSpawnEvent_Struct));
ServerSpawnEvent_Struct* sse = (ServerSpawnEvent_Struct*)pack->pBuffer;
sse->zoneID = database.GetZoneID(zone_short_name.c_str());
sse->zoneID = ZoneID(zone_short_name.c_str());
sse->event_id = event_id;
worldserver.SendPacket(pack);
+23 -2
View File
@@ -24,6 +24,8 @@
#include "spawngroup.h"
#include "zone.h"
#include "zonedb.h"
#include "zone_store.h"
#include "../common/repositories/criteria/content_filter_criteria.h"
extern EntityList entity_list;
extern Zone *zone;
@@ -176,7 +178,7 @@ bool SpawnGroupList::RemoveSpawnGroup(uint32 in_id)
void SpawnGroupList::ReloadSpawnGroups()
{
ClearSpawnGroups();
database.LoadSpawnGroups(zone->GetShortName(), zone->GetInstanceVersion(), &zone->spawn_group_list);
content_db.LoadSpawnGroups(zone->GetShortName(), zone->GetInstanceVersion(), &zone->spawn_group_list);
}
void SpawnGroupList::ClearSpawnGroups()
@@ -209,9 +211,11 @@ bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnG
spawn2.spawngroupID = spawngroup.ID
AND
spawn2.version = {} and zone = '{}'
{}
),
version,
zone_name
zone_name,
ContentFilterCriteria::apply()
);
auto results = QueryDatabase(query);
@@ -325,6 +329,14 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawn_group_id, SpawnGroupList *spawn
}
for (auto row = results.begin(); row != results.end(); ++row) {
LogSpawnsDetail(
"[LoadSpawnGroupsByID] Loading spawn_group spawn_group_id [{}] name [{}] spawn_limit [{}] dist [{}]",
row[0],
row[1],
row[2],
row[3]
);
auto new_spawn_group = new SpawnGroup(
atoi(row[0]),
row[1],
@@ -375,6 +387,15 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawn_group_id, SpawnGroupList *spawn
(row[4] ? atoi(row[4]) : 0)
);
LogSpawnsDetail(
"[LoadSpawnGroupsByID] Loading spawn_entry spawn_group_id [{}] npc_id [{}] chance [{}] condition_value_filter [{}] spawn_limit [{}]",
row[0],
row[1],
row[2],
row[3],
row[4]
);
SpawnGroup *spawn_group = spawn_group_list->GetSpawnGroup(atoi(row[0]));
if (!spawn_group) {
safe_delete(new_spawn_entry);
+1
View File
@@ -310,6 +310,7 @@
#define WHOALL_NO_RESULTS 5029 //There are no players in EverQuest that match those who filters.
#define TELL_QUEUED_MESSAGE 5045 //You told %1 '%T2. %3'
#define TOLD_NOT_ONLINE 5046 //%1 is not online at this time.
#define ZONING_NO_EXPANSION 5052 //The zone that you are attempting to enter is part of an expansion that you do not yet own. You may need to return to the Login screen and enter an account key for that expansion. If you have received this message in error, please /petition or send an email to EQAccounts@soe.sony.com
#define PETITION_NO_DELETE 5053 //You do not have a petition in the queue.
#define PETITION_DELETED 5054 //Your petition was successfully deleted.
#define ALREADY_IN_RAID 5060 //%1 is already in a raid.
+33 -29
View File
@@ -30,7 +30,9 @@ Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
#include "../common/rulesys.h"
#include "../common/string_util.h"
#include "../common/say_link.h"
#include "zonedb.h"
#include "zone_store.h"
#include "../common/repositories/goallists_repository.h"
#include "client.h"
#include "entity.h"
#include "mob.h"
@@ -69,7 +71,7 @@ bool TaskManager::LoadTaskSets()
"ORDER BY `id`, `taskid` ASC",
MAXTASKSETS, MAXTASKS
);
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
LogError("Error in TaskManager::LoadTaskSets: [{}]", results.ErrorMessage().c_str());
return false;
@@ -131,7 +133,7 @@ bool TaskManager::LoadTasks(int singleTask)
const char *ERR_MYSQLERROR = "[TASKS]Error in TaskManager::LoadTasks: %s";
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
LogError(ERR_MYSQLERROR, results.ErrorMessage().c_str());
return false;
@@ -188,7 +190,7 @@ bool TaskManager::LoadTasks(int singleTask)
"`goalcount`, `delivertonpc`, `zones`, `optional` FROM `task_activities` WHERE `taskid` = "
"%i AND `activityid` < %i ORDER BY taskid, activityid ASC",
singleTask, MAXACTIVITIESPERTASK);
results = database.QueryDatabase(query);
results = content_db.QueryDatabase(query);
if (!results.Success()) {
LogError(ERR_MYSQLERROR, results.ErrorMessage().c_str());
return false;
@@ -982,7 +984,7 @@ int TaskManager::GetTaskMinLevel(int TaskID)
{
return Tasks[TaskID]->MinLevel;
}
return -1;
}
@@ -3422,7 +3424,7 @@ bool TaskGoalListManager::LoadLists()
std::string query = "SELECT `listid`, COUNT(`entry`) "
"FROM `goallists` GROUP by `listid` "
"ORDER BY `listid`";
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
return false;
}
@@ -3432,42 +3434,44 @@ bool TaskGoalListManager::LoadLists()
TaskGoalLists.reserve(NumberOfLists);
int listIndex = 0;
int list_index = 0;
for (auto row = results.begin(); row != results.end(); ++row) {
int listID = atoi(row[0]);
int listID = atoi(row[0]);
int listSize = atoi(row[1]);
TaskGoalLists.push_back({listID, 0, 0});
TaskGoalLists[listIndex].GoalItemEntries.reserve(listSize);
TaskGoalLists[list_index].GoalItemEntries.reserve(listSize);
listIndex++;
list_index++;
}
for (int listIndex = 0; listIndex < NumberOfLists; listIndex++) {
auto goal_lists = GoallistsRepository::GetWhere("TRUE ORDER BY listid, entry ASC");
int listID = TaskGoalLists[listIndex].ListID;
auto size = TaskGoalLists[listIndex].GoalItemEntries.capacity(); // this was only done for manual memory management, shouldn't need to do this
query = StringFormat("SELECT `entry` from `goallists` "
"WHERE `listid` = %i "
"ORDER BY `entry` ASC LIMIT %i",
listID, size);
results = database.QueryDatabase(query);
if (!results.Success()) {
continue;
}
for (list_index = 0; list_index < NumberOfLists; list_index++) {
for (auto row = results.begin(); row != results.end(); ++row) {
int list_id = TaskGoalLists[list_index].ListID;
int entry = atoi(row[0]);
for (auto &entry: goal_lists) {
if (entry.listid == list_id) {
if (entry.entry < TaskGoalLists[list_index].Min) {
TaskGoalLists[list_index].Min = entry.entry;
}
if (entry < TaskGoalLists[listIndex].Min)
TaskGoalLists[listIndex].Min = entry;
if (entry.entry > TaskGoalLists[list_index].Max) {
TaskGoalLists[list_index].Max = entry.entry;
}
if (entry > TaskGoalLists[listIndex].Max)
TaskGoalLists[listIndex].Max = entry;
TaskGoalLists[list_index].GoalItemEntries.push_back(entry.entry);
TaskGoalLists[listIndex].GoalItemEntries.push_back(entry);
LogTasksDetail(
"Goal list index [{}] loading list [{}] entry [{}]",
list_index,
list_id,
entry.entry
);
}
}
}
@@ -3557,7 +3561,7 @@ bool TaskProximityManager::LoadProximities(int zoneID) {
"`miny`, `maxy`, `minz`, `maxz` "
"FROM `proximities` WHERE `zoneid` = %i "
"ORDER BY `zoneid` ASC", zoneID);
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
return false;
}
+341 -185
View File
@@ -33,6 +33,9 @@
#include "string_ids.h"
#include "titles.h"
#include "zonedb.h"
#include "zone_store.h"
#include "../common/repositories/character_recipe_list_repository.h"
#include "../common/repositories/tradeskill_recipe_repository.h"
extern QueryServ* QServ;
@@ -256,27 +259,39 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob
return;
}
EQ::InventoryProfile& user_inv = user->GetInv();
PlayerProfile_Struct& user_pp = user->GetPP();
EQ::ItemInstance* container = nullptr;
EQ::ItemInstance* inst = nullptr;
uint8 c_type = 0xE8;
uint32 some_id = 0;
bool worldcontainer=false;
LogTradeskills(
"[HandleCombine] container_slot [{}] guildtribute_slot [{}]",
in_combine->container_slot,
in_combine->guildtribute_slot
);
EQ::InventoryProfile &user_inv = user->GetInv();
PlayerProfile_Struct &user_pp = user->GetPP();
EQ::ItemInstance *container = nullptr;
EQ::ItemInstance *inst = nullptr;
uint8 c_type = 0xE8;
uint32 some_id = 0;
bool worldcontainer = false;
if (in_combine->container_slot == EQ::invslot::SLOT_TRADESKILL_EXPERIMENT_COMBINE) {
if(!worldo) {
user->Message(Chat::Red, "Error: Server is not aware of the tradeskill container you are attempting to use");
user->Message(
Chat::Red,
"Error: Server is not aware of the tradeskill container you are attempting to use"
);
return;
}
c_type = worldo->m_type;
inst = worldo->m_inst;
worldcontainer=true;
c_type = worldo->m_type;
inst = worldo->m_inst;
worldcontainer = true;
// if we're a world container with an item, use that too
if (inst) {
const EQ::ItemData* item = inst->GetItem();
if (item)
const EQ::ItemData *item = inst->GetItem();
if (item) {
some_id = item->ID;
}
}
}
else {
@@ -297,16 +312,31 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob
container = inst;
if (container->GetItem() && container->GetItem()->BagType == EQ::item::BagTypeTransformationmold) {
const EQ::ItemInstance* inst = container->GetItem(0);
bool AllowAll = RuleB(Inventory, AllowAnyWeaponTransformation);
const EQ::ItemInstance *inst = container->GetItem(0);
bool AllowAll = RuleB(Inventory, AllowAnyWeaponTransformation);
if (inst && EQ::ItemInstance::CanTransform(inst->GetItem(), container->GetItem(), AllowAll)) {
const EQ::ItemData* new_weapon = inst->GetItem();
const EQ::ItemData *new_weapon = inst->GetItem();
user->DeleteItemInInventory(EQ::InventoryProfile::CalcSlotId(in_combine->container_slot, 0), 0, true);
container->Clear();
user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), EQ::invslot::slotCursor, container->GetItem()->Icon, atoi(container->GetItem()->IDFile + 2));
user->SummonItem(
new_weapon->ID,
inst->GetCharges(),
inst->GetAugmentItemID(0),
inst->GetAugmentItemID(1),
inst->GetAugmentItemID(2),
inst->GetAugmentItemID(3),
inst->GetAugmentItemID(4),
inst->GetAugmentItemID(5),
inst->IsAttuned(),
EQ::invslot::slotCursor,
container->GetItem()->Icon,
atoi(container->GetItem()->IDFile + 2)
);
user->MessageString(Chat::LightBlue, TRANSFORM_COMPLETE, inst->GetItem()->Name);
if (RuleB(Inventory, DeleteTransformationMold))
if (RuleB(Inventory, DeleteTransformationMold)) {
user->DeleteItemInInventory(in_combine->container_slot, 0, true);
}
}
else if (inst) {
user->MessageString(Chat::LightBlue, TRANSFORM_FAILED, inst->GetItem()->Name);
@@ -314,10 +344,19 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob
auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0);
user->QueuePacket(outapp);
safe_delete(outapp);
LogTradeskills(
"[HandleCombine] inst_item [{}] container_item [{}]",
inst->GetItem()->ID,
container->GetItem()->ID
);
return;
}
if (container->GetItem() && container->GetItem()->BagType == EQ::item::BagTypeDetransformationmold) {
LogTradeskillsDetail("[HandleCombine] Check 1");
const EQ::ItemInstance* inst = container->GetItem(0);
if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIcon()) {
const EQ::ItemData* new_weapon = inst->GetItem();
@@ -336,7 +375,10 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob
}
DBTradeskillRecipe_Struct spec;
if (!database.GetTradeRecipe(container, c_type, some_id, user->CharacterID(), &spec)) {
if (!content_db.GetTradeRecipe(container, c_type, some_id, user->CharacterID(), &spec)) {
LogTradeskillsDetail("[HandleCombine] Check 2");
user->MessageString(Chat::Emote,TRADESKILL_NOCOMBINE);
auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0);
user->QueuePacket(outapp);
@@ -350,7 +392,10 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob
// bit 2 (0x02): can try to experiment but not useable for auto-combine until learnt
// bit 5 (0x10): no learn message, use unlisted flag to prevent it showing up on search
// bit 6 (0x20): unlisted recipe flag
if ((spec.must_learn&0xF) == 1 && !spec.has_learnt) {
if ((spec.must_learn & 0xF) == 1 && !spec.has_learnt) {
LogTradeskillsDetail("[HandleCombine] Check 3");
// Made up message for the client. Just giving a DNC is the other option.
user->Message(Chat::LightBlue, "You need to learn how to combine these first.");
auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0);
@@ -360,6 +405,9 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob
}
// Character does not have the required skill.
if(spec.skill_needed > 0 && user->GetSkill(spec.tradeskill) < spec.skill_needed ) {
LogTradeskillsDetail("Check 4");
// Notify client.
user->Message(Chat::LightBlue, "You are not skilled enough.");
auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0);
@@ -439,18 +487,21 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob
// Replace the container on success if required.
//
if(success && spec.replace_container) {
if(worldcontainer){
if (success && spec.replace_container) {
if (worldcontainer) {
//should report this error, but we dont have the recipe ID, so its not very useful
LogError("Replace container combine executed in a world container");
}
else
else {
user->DeleteItemInInventory(in_combine->container_slot, 0, true);
}
}
if (success)
if (success) {
parse->EventPlayer(EVENT_COMBINE_SUCCESS, user, spec.name.c_str(), spec.recipe_id);
else
}
else {
parse->EventPlayer(EVENT_COMBINE_FAILURE, user, spec.name.c_str(), spec.recipe_id);
}
}
void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac) {
@@ -467,7 +518,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac
//ask the database for the recipe to make sure it exists...
DBTradeskillRecipe_Struct spec;
if (!database.GetTradeRecipe(rac->recipe_id, rac->object_type, rac->some_id, user->CharacterID(), &spec)) {
if (!content_db.GetTradeRecipe(rac->recipe_id, rac->object_type, rac->some_id, user->CharacterID(), &spec)) {
LogError("Unknown recipe for HandleAutoCombine: [{}]\n", rac->recipe_id);
user->QueuePacket(outapp);
safe_delete(outapp);
@@ -489,7 +540,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac
"FROM tradeskill_recipe_entries AS tre "
"WHERE tre.componentcount > 0 AND tre.recipe_id = %u",
rac->recipe_id);
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
user->QueuePacket(outapp);
safe_delete(outapp);
@@ -704,62 +755,75 @@ EQ::skills::SkillType Object::TypeToSkill(uint32 type)
}
}
void Client::TradeskillSearchResults(const std::string &query, unsigned long objtype, unsigned long someid) {
auto results = database.QueryDatabase(query);
void Client::SendTradeskillSearchResults(
const std::string &query,
unsigned long objtype,
unsigned long someid
)
{
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
return;
}
if(results.RowCount() < 1)
return; //search gave no results... not an error
if(results.ColumnCount() != 6) {
LogError("Error in TradeskillSearchResults query [{}]: Invalid column count in result", query.c_str());
if (results.RowCount() < 1) {
return;
}
for(auto row = results.begin(); row != results.end(); ++row) {
if(row == nullptr || row[0] == nullptr || row[1] == nullptr || row[2] == nullptr || row[3] == nullptr || row[5] == nullptr)
continue;
auto character_learned_recipe_list = CharacterRecipeListRepository::GetLearnedRecipeList(CharacterID());
uint32 recipe = (uint32)atoi(row[0]);
const char *name = row[1];
uint32 trivial = (uint32) atoi(row[2]);
uint32 comp_count = (uint32) atoi(row[3]);
uint32 tradeskill = (uint16) atoi(row[5]);
for (auto row = results.begin(); row != results.end(); ++row) {
if (row == nullptr || row[0] == nullptr || row[1] == nullptr || row[2] == nullptr || row[3] == nullptr ||
row[5] == nullptr) {
continue;
}
uint32 recipe_id = (uint32) atoi(row[0]);
const char *name = row[1];
uint32 trivial = (uint32) atoi(row[2]);
uint32 comp_count = (uint32) atoi(row[3]);
uint32 tradeskill = (uint16) atoi(row[5]);
// Skip the recipes that exceed the threshold in skill difference
// Recipes that have either been made before or were
// explicitly learned are excempt from that limit
if (RuleB(Skills, UseLimitTradeskillSearchSkillDiff)
&& ((int32)trivial - (int32)GetSkill((EQ::skills::SkillType)tradeskill)) > RuleI(Skills, MaxTradeskillSearchSkillDiff)
&& row[4] == nullptr)
continue;
if (RuleB(Skills, UseLimitTradeskillSearchSkillDiff) &&
((int32) trivial - (int32) GetSkill((EQ::skills::SkillType) tradeskill)) >
RuleI(Skills, MaxTradeskillSearchSkillDiff)) {
auto outapp = new EQApplicationPacket(OP_RecipeReply, sizeof(RecipeReply_Struct));
LogTradeskills("Checking limit recipe_id [{}] name [{}]", recipe_id, name);
auto character_learned_recipe = CharacterRecipeListRepository::GetRecipe(
character_learned_recipe_list,
recipe_id
);
if (character_learned_recipe.made_count == 0) {
continue;
}
}
auto outapp = new EQApplicationPacket(OP_RecipeReply, sizeof(RecipeReply_Struct));
RecipeReply_Struct *reply = (RecipeReply_Struct *) outapp->pBuffer;
reply->object_type = objtype;
reply->some_id = someid;
reply->object_type = objtype;
reply->some_id = someid;
reply->component_count = comp_count;
reply->recipe_id = recipe;
reply->trivial = trivial;
reply->recipe_id = recipe_id;
reply->trivial = trivial;
strn0cpy(reply->recipe_name, name, sizeof(reply->recipe_name));
FastQueuePacket(&outapp);
}
}
void Client::SendTradeskillDetails(uint32 recipe_id) {
//pull the list of components
std::string query = StringFormat("SELECT tre.item_id,tre.componentcount,i.icon,i.Name "
"FROM tradeskill_recipe_entries AS tre "
"LEFT JOIN items AS i ON tre.item_id = i.id "
"WHERE tre.componentcount > 0 AND tre.recipe_id = %u",
recipe_id);
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
return;
}
@@ -978,7 +1042,7 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) {
aa_chance = spellbonuses.ReduceTradeskillFail[spec->tradeskill] + itembonuses.ReduceTradeskillFail[spec->tradeskill] + aabonuses.ReduceTradeskillFail[spec->tradeskill];
const EQ::ItemData* item = nullptr;
chance = mod_tradeskill_chance(chance, spec);
if (((spec->tradeskill==75) || GetGM() || (chance > res)) || zone->random.Roll(aa_chance)) {
@@ -1124,50 +1188,75 @@ void Client::CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float
NotifyNewTitlesAvailable();
}
LogTradeskills("skillup_modifier: [{}] , success_modifier: [{}] , stat modifier: [{}]", skillup_modifier , success_modifier , stat_modifier);
LogTradeskills("Stage1 chance was: [{}] percent", chance_stage1);
LogTradeskills("Stage2 chance was: [{}] percent. 0 percent means stage1 failed", chance_stage2);
LogTradeskills("[CheckIncreaseTradeskill] skillup_modifier: [{}] , success_modifier: [{}] , stat modifier: [{}]", skillup_modifier , success_modifier , stat_modifier);
LogTradeskills("[CheckIncreaseTradeskill] Stage1 chance was: [{}] percent", chance_stage1);
LogTradeskills("[CheckIncreaseTradeskill] Stage2 chance was: [{}] percent. 0 percent means stage1 failed", chance_stage2);
}
bool ZoneDatabase::GetTradeRecipe(const EQ::ItemInstance* container, uint8 c_type, uint32 some_id,
uint32 char_id, DBTradeskillRecipe_Struct *spec)
bool ZoneDatabase::GetTradeRecipe(
const EQ::ItemInstance *container,
uint8 c_type,
uint32 some_id,
uint32 char_id,
DBTradeskillRecipe_Struct *spec
)
{
if (container == nullptr)
if (container == nullptr) {
LogTradeskills("[GetTradeRecipe] Container null");
return false;
}
std::string containers;// make where clause segment for container(s)
if (some_id == 0)
if (some_id == 0) {
containers = StringFormat("= %u", c_type); // world combiner so no item number
else
containers = StringFormat("IN (%u,%u)", c_type, some_id); // container in inventory
}
else {
containers = StringFormat("IN (%u,%u)", c_type, some_id);
} // container in inventory
//Could prolly watch for stacks in this loop and handle them properly...
//just increment sum and count accordingly
bool first = true;
bool first = true;
std::string buf2;
uint32 count = 0;
uint32 sum = 0;
for (uint8 i = 0; i < 10; i++) { // <watch> TODO: need to determine if this is bound to world/item container size
const EQ::ItemInstance* inst = container->GetItem(i);
if (!inst)
continue;
uint32 count = 0;
uint32 sum = 0;
for (uint8 i = 0; i < 10; i++) { // <watch> TODO: need to determine if this is bound to world/item container size
LogTradeskills("[GetTradeRecipe] Fetching item [{}]", i);
const EQ::ItemData* item = GetItem(inst->GetItem()->ID);
if (!item)
continue;
const EQ::ItemInstance *inst = container->GetItem(i);
if (!inst) {
continue;
}
if(first) {
buf2 += StringFormat("%d", item->ID);
first = false;
} else
buf2 += StringFormat(",%d", item->ID);
const EQ::ItemData *item = database.GetItem(inst->GetItem()->ID);
if (!item) {
LogTradeskills("[GetTradeRecipe] item [{}] not found!", inst->GetItem()->ID);
continue;
}
sum += item->ID;
count++;
if (first) {
buf2 += StringFormat("%d", item->ID);
first = false;
}
else {
buf2 += StringFormat(",%d", item->ID);
}
sum += item->ID;
count++;
LogTradeskills(
"[GetTradeRecipe] Item in container index [{}] item [{}] found [{}]",
i,
item->ID,
count
);
}
if(count == 0)
return false; //no items == no recipe
//no items == no recipe
if (count == 0) {
return false;
}
std::string query = StringFormat("SELECT tre.recipe_id "
"FROM tradeskill_recipe_entries AS tre "
@@ -1201,23 +1290,24 @@ bool ZoneDatabase::GetTradeRecipe(const EQ::ItemInstance* container, uint8 c_typ
//length limit on buf2
if(index == 214) { //Maximum number of recipe matches (19 * 215 = 4096)
LogError("GetTradeRecipe warning: Too many matches. Unable to search all recipe entries. Searched [{}] of [{}] possible entries", index + 1, results.RowCount());
LogError("GetTradeRecipe warning: Too many matches. Unable to search all recipe entries. Searched [{}] of [{}] possible entries", index + 1, results.RowCount());
break;
}
}
query = StringFormat("SELECT tre.recipe_id "
"FROM tradeskill_recipe_entries AS tre "
"WHERE tre.recipe_id IN (%s) "
"GROUP BY tre.recipe_id HAVING sum(tre.componentcount) = %u "
"AND sum(tre.item_id * tre.componentcount) = %u", buf2.c_str(), count, sum);
"WHERE tre.recipe_id IN (%s) "
"GROUP BY tre.recipe_id HAVING sum(tre.componentcount) = %u "
"AND sum(tre.item_id * tre.componentcount) = %u", buf2.c_str(), count, sum
);
results = QueryDatabase(query);
if (!results.Success()) {
LogError("Error in GetTradeRecipe, re-query: [{}]", query.c_str());
LogError("Error in GetTradeRecipe, error: [{}]", results.ErrorMessage().c_str());
return false;
}
}
if (!results.Success()) {
LogError("Error in GetTradeRecipe, re-query: [{}]", query.c_str());
LogError("Error in GetTradeRecipe, error: [{}]", results.ErrorMessage().c_str());
return false;
}
}
if (results.RowCount() < 1)
return false;
@@ -1279,55 +1369,87 @@ bool ZoneDatabase::GetTradeRecipe(const EQ::ItemInstance* container, uint8 c_typ
return GetTradeRecipe(recipe_id, c_type, some_id, char_id, spec);
}
if (results.RowCount() == 0)
return GetTradeRecipe(recipe_id, c_type, some_id, char_id, spec);
if (results.RowCount() == 0) {
return GetTradeRecipe(recipe_id, c_type, some_id, char_id, spec);
}
for (auto row = results.begin(); row != results.end(); ++row) {
int ccnt = 0;
int component_count = 0;
for (int x = EQ::invbag::SLOT_BEGIN; x < EQ::invtype::WORLD_SIZE; x++) {
const EQ::ItemInstance* inst = container->GetItem(x);
if(!inst)
continue;
const EQ::ItemData* item = GetItem(inst->GetItem()->ID);
const EQ::ItemData* item = database.GetItem(inst->GetItem()->ID);
if (!item)
continue;
if(item->ID == atoi(row[0]))
ccnt++;
}
if (item->ID == atoi(row[0])) {
component_count++;
}
if(ccnt != atoi(row[1]))
return false;
}
LogTradeskills(
"[GetTradeRecipe] Component count loop [{}] item [{}] recipe component_count [{}]",
component_count,
item->ID,
atoi(row[1])
);
}
if (component_count != atoi(row[1])) {
return false;
}
}
return GetTradeRecipe(recipe_id, c_type, some_id, char_id, spec);
}
bool ZoneDatabase::GetTradeRecipe(uint32 recipe_id, uint8 c_type, uint32 some_id,
uint32 char_id, DBTradeskillRecipe_Struct *spec)
bool ZoneDatabase::GetTradeRecipe(
uint32 recipe_id,
uint8 c_type,
uint32 some_id,
uint32 char_id,
DBTradeskillRecipe_Struct *spec
)
{
// make where clause segment for container(s)
std::string containers;
if (some_id == 0)
containers = StringFormat("= %u", c_type); // world combiner so no item number
else
containers = StringFormat("IN (%u,%u)", c_type, some_id); // container in inventory
std::string container_where_filter;
if (some_id == 0) {
// world combiner so no item number
container_where_filter = StringFormat("= %u", c_type);
}
else {
// container in inventory
container_where_filter = StringFormat("IN (%u,%u)", c_type, some_id);
}
std::string query = StringFormat("SELECT tr.id, tr.tradeskill, tr.skillneeded, "
"tr.trivial, tr.nofail, tr.replace_container, "
"tr.name, tr.must_learn, tr.quest, crl.madecount "
"FROM tradeskill_recipe AS tr "
"INNER JOIN tradeskill_recipe_entries AS tre "
"ON tr.id = tre.recipe_id "
"LEFT JOIN (SELECT recipe_id, madecount "
"FROM char_recipe_list WHERE char_id = %u) AS crl "
"ON tr.id = crl.recipe_id "
"WHERE tr.id = %lu AND tre.item_id %s AND tr.enabled "
"GROUP BY tr.id",
char_id, (unsigned long)recipe_id, containers.c_str());
std::string query = StringFormat(
SQL (
SELECT
tradeskill_recipe.id,
tradeskill_recipe.tradeskill,
tradeskill_recipe.skillneeded,
tradeskill_recipe.trivial,
tradeskill_recipe.nofail,
tradeskill_recipe.replace_container,
tradeskill_recipe.name,
tradeskill_recipe.must_learn,
tradeskill_recipe.quest
FROM
tradeskill_recipe
INNER JOIN tradeskill_recipe_entries ON tradeskill_recipe.id = tradeskill_recipe_entries.recipe_id
WHERE
tradeskill_recipe.id = %lu
AND tradeskill_recipe_entries.item_id %s
AND tradeskill_recipe.enabled
GROUP BY
tradeskill_recipe.id
)
,
(unsigned long) recipe_id,
container_where_filter.c_str()
);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogError("Error in GetTradeRecipe, query: [{}]", query.c_str());
@@ -1335,27 +1457,36 @@ bool ZoneDatabase::GetTradeRecipe(uint32 recipe_id, uint8 c_type, uint32 some_id
return false;
}
if(results.RowCount() != 1)
return false;//just not found i guess..
if (results.RowCount() != 1) {
return false;
}
auto row = results.begin();
spec->tradeskill = (EQ::skills::SkillType)atoi(row[1]);
spec->skill_needed = (int16)atoi(row[2]);
spec->trivial = (uint16)atoi(row[3]);
spec->nofail = atoi(row[4]) ? true : false;
spec->replace_container = atoi(row[5]) ? true : false;
spec->name = row[6];
spec->must_learn = (uint8)atoi(row[7]);
spec->quest = atoi(row[8]) ? true : false;
if (row[9] == nullptr) {
spec->has_learnt = false;
spec->madecount = 0;
} else {
spec->tradeskill = (EQ::skills::SkillType) atoi(row[1]);
spec->skill_needed = (int16) atoi(row[2]);
spec->trivial = (uint16) atoi(row[3]);
spec->nofail = atoi(row[4]) ? true : false;
spec->replace_container = atoi(row[5]) ? true : false;
spec->name = row[6];
spec->must_learn = (uint8) atoi(row[7]);
spec->quest = atoi(row[8]) ? true : false;
spec->has_learnt = false;
spec->madecount = 0;
spec->recipe_id = recipe_id;
auto character_learned_recipe_list = CharacterRecipeListRepository::GetLearnedRecipeList(char_id);
auto character_learned_recipe = CharacterRecipeListRepository::GetRecipe(
character_learned_recipe_list,
recipe_id
);
if (character_learned_recipe.made_count > 0) {
LogTradeskills("[GetTradeRecipe] made_count [{}]", character_learned_recipe.made_count);
spec->has_learnt = true;
spec->madecount = (uint32)atoul(row[9]);
spec->madecount = (uint32)character_learned_recipe.made_count;
}
spec->recipe_id = recipe_id;
//Pull the on-success items...
query = StringFormat("SELECT item_id,successcount FROM tradeskill_recipe_entries "
@@ -1379,33 +1510,41 @@ bool ZoneDatabase::GetTradeRecipe(uint32 recipe_id, uint8 c_type, uint32 some_id
spec->onfail.clear();
//Pull the on-fail items...
query = StringFormat("SELECT item_id, failcount FROM tradeskill_recipe_entries "
"WHERE failcount > 0 AND recipe_id = %u", recipe_id);
query = StringFormat(
"SELECT item_id, failcount FROM tradeskill_recipe_entries "
"WHERE failcount > 0 AND recipe_id = %u", recipe_id
);
results = QueryDatabase(query);
if (results.Success())
for(auto row = results.begin(); row != results.end(); ++row) {
uint32 item = (uint32)atoi(row[0]);
uint8 num = (uint8) atoi(row[1]);
spec->onfail.push_back(std::pair<uint32,uint8>(item, num));
if (results.Success()) {
for (auto row = results.begin(); row != results.end(); ++row) {
uint32 item = (uint32) atoi(row[0]);
uint8 num = (uint8) atoi(row[1]);
spec->onfail.push_back(std::pair<uint32, uint8>(item, num));
}
}
spec->salvage.clear();
spec->salvage.clear();
// Don't bother with the query if TS is nofail
if (spec->nofail)
return true;
// Don't bother with the query if TS is nofail
if (spec->nofail) {
return true;
}
// Pull the salvage list
query = StringFormat("SELECT item_id, salvagecount "
"FROM tradeskill_recipe_entries "
"WHERE salvagecount > 0 AND recipe_id = %u", recipe_id);
results = QueryDatabase(query);
if (results.Success())
for(auto row = results.begin(); row != results.begin(); ++row) {
uint32 item = (uint32)atoi(row[0]);
uint8 num = (uint8)atoi(row[1]);
spec->salvage.push_back(std::pair<uint32,uint8>(item, num));
query = StringFormat(
"SELECT item_id, salvagecount "
"FROM tradeskill_recipe_entries "
"WHERE salvagecount > 0 AND recipe_id = %u", recipe_id
);
results = QueryDatabase(query);
if (results.Success()) {
for (auto row = results.begin(); row != results.begin(); ++row) {
uint32 item = (uint32) atoi(row[0]);
uint8 num = (uint8) atoi(row[1]);
spec->salvage.push_back(std::pair<uint32, uint8>(item, num));
}
}
return true;
}
@@ -1419,40 +1558,57 @@ void ZoneDatabase::UpdateRecipeMadecount(uint32 recipe_id, uint32 char_id, uint3
QueryDatabase(query);
}
void Client::LearnRecipe(uint32 recipeID)
void Client::LearnRecipe(uint32 recipe_id)
{
std::string query = StringFormat("SELECT tr.name, crl.madecount "
"FROM tradeskill_recipe AS tr "
"LEFT JOIN (SELECT recipe_id, madecount "
"FROM char_recipe_list WHERE char_id = %u) AS crl "
"ON tr.id = crl.recipe_id "
"WHERE tr.id = %u ;", CharacterID(), recipeID);
auto results = database.QueryDatabase(query);
std::string query = fmt::format(
SQL(
select
char_id,
recipe_id,
madecount
from
char_recipe_list
where
char_id = {}
and recipe_id = {}
LIMIT 1
),
CharacterID(),
recipe_id
);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
return;
}
if (results.RowCount() != 1) {
LogInfo("Client::LearnRecipe - RecipeID: [{}] had [{}] occurences", recipeID, results.RowCount());
auto tradeskill_recipe = TradeskillRecipeRepository::FindOne(recipe_id);
if (tradeskill_recipe.id == 0) {
LogError("Invalid recipe [{}]", recipe_id);
return;
}
LogTradeskills(
"[LearnRecipe] recipe_id [{}] name [{}] learned [{}]",
recipe_id,
tradeskill_recipe.name,
results.RowCount()
);
auto row = results.begin();
if (results.RowCount() > 0) {
return;
}
if (row[0] == nullptr)
return;
MessageString(Chat::LightBlue, TRADESKILL_LEARN_RECIPE, tradeskill_recipe.name.c_str());
// Only give Learn message if character doesn't know the recipe
if (row[1] != nullptr)
return;
MessageString(Chat::LightBlue, TRADESKILL_LEARN_RECIPE, row[0]);
// Actually learn the recipe now
query = StringFormat("INSERT INTO char_recipe_list "
"SET recipe_id = %u, char_id = %u, madecount = 0 "
"ON DUPLICATE KEY UPDATE madecount = madecount;",
recipeID, CharacterID());
results = database.QueryDatabase(query);
database.QueryDatabase(
fmt::format(
"REPLACE INTO char_recipe_list (recipe_id, char_id, madecount) VALUES ({}, {}, 0)",
recipe_id,
CharacterID()
)
);
}
bool Client::CanIncreaseTradeskill(EQ::skills::SkillType tradeskill) {
@@ -1471,8 +1627,8 @@ bool Client::CanIncreaseTradeskill(EQ::skills::SkillType tradeskill) {
uint8 Tailoring = (GetRawSkill(EQ::skills::SkillTailoring) > 200) ? 1 : 0;
uint8 SkillTotal = Baking + Smithing + Brewing + Fletching + Jewelry + Pottery + Tailoring; //Tradeskills above 200
//New Tanaan AA: Each level allows an additional tradeskill above 200 (first one is free)
uint8 aaLevel = spellbonuses.TradeSkillMastery + itembonuses.TradeSkillMastery + aabonuses.TradeSkillMastery;
uint8 aaLevel = spellbonuses.TradeSkillMastery + itembonuses.TradeSkillMastery + aabonuses.TradeSkillMastery;
switch (tradeskill) {
case EQ::skills::SkillBaking:
case EQ::skills::SkillBlacksmithing:
+265 -236
View File
@@ -1755,286 +1755,315 @@ void Client::SendBazaarWelcome()
"or use /buyer to set up your own Buy Lines.", atoi(row[0]));
}
void Client::SendBazaarResults(uint32 TraderID, uint32 Class_, uint32 Race, uint32 ItemStat, uint32 Slot, uint32 Type,
char Name[64], uint32 MinPrice, uint32 MaxPrice) {
void Client::SendBazaarResults(
uint32 trader_id,
uint32 in_class,
uint32 in_race,
uint32 item_stat,
uint32 item_slot,
uint32 item_type,
char item_name[64],
uint32 min_price,
uint32 max_price
)
{
std::string search_values = " COUNT(item_id), trader.*, items.name ";
std::string search_criteria = " WHERE trader.item_id = items.id ";
std::string searchValues = " COUNT(item_id), trader.*, items.name ";
std::string searchCriteria = " WHERE trader.item_id = items.id ";
if (trader_id > 0) {
Client *trader = entity_list.GetClientByID(trader_id);
if(TraderID > 0) {
Client* trader = entity_list.GetClientByID(TraderID);
if(trader)
searchCriteria.append(StringFormat(" AND trader.char_id = %i", trader->CharacterID()));
if (trader) {
search_criteria.append(StringFormat(" AND trader.char_id = %i", trader->CharacterID()));
}
}
if(MinPrice != 0)
searchCriteria.append(StringFormat(" AND trader.item_cost >= %i", MinPrice));
if (min_price != 0) {
search_criteria.append(StringFormat(" AND trader.item_cost >= %i", min_price));
}
if(MaxPrice != 0)
searchCriteria.append(StringFormat(" AND trader.item_cost <= %i", MaxPrice));
if (max_price != 0) {
search_criteria.append(StringFormat(" AND trader.item_cost <= %i", max_price));
}
if(strlen(Name) > 0) {
char *safeName = RemoveApostrophes(Name);
searchCriteria.append(StringFormat(" AND items.name LIKE '%%%s%%'", safeName));
if (strlen(item_name) > 0) {
char *safeName = RemoveApostrophes(item_name);
search_criteria.append(StringFormat(" AND items.name LIKE '%%%s%%'", safeName));
safe_delete_array(safeName);
}
if(Class_ != 0xFFFFFFFF)
searchCriteria.append(StringFormat(" AND MID(REVERSE(BIN(items.classes)), %i, 1) = 1", Class_));
if (in_class != 0xFFFFFFFF) {
search_criteria.append(StringFormat(" AND MID(REVERSE(BIN(items.classes)), %i, 1) = 1", in_class));
}
if(Race != 0xFFFFFFFF)
searchCriteria.append(StringFormat(" AND MID(REVERSE(BIN(items.races)), %i, 1) = 1", Race));
if (in_race != 0xFFFFFFFF) {
search_criteria.append(StringFormat(" AND MID(REVERSE(BIN(items.races)), %i, 1) = 1", in_race));
}
if(Slot != 0xFFFFFFFF)
searchCriteria.append(StringFormat(" AND MID(REVERSE(BIN(items.slots)), %i, 1) = 1", Slot + 1));
if (item_slot != 0xFFFFFFFF) {
search_criteria.append(StringFormat(" AND MID(REVERSE(BIN(items.slots)), %i, 1) = 1", item_slot + 1));
}
switch(Type){
case 0xFFFFFFFF:
break;
case 0:
// 1H Slashing
searchCriteria.append(" AND items.itemtype = 0 AND damage > 0");
break;
case 31:
searchCriteria.append(" AND items.itemclass = 2");
break;
case 46:
searchCriteria.append(" AND items.spellid > 0 AND items.spellid < 65000");
break;
case 47:
searchCriteria.append(" AND items.spellid = 998");
break;
case 48:
searchCriteria.append(" AND items.spellid >= 1298 AND items.spellid <= 1307");
break;
case 49:
searchCriteria.append(" AND items.focuseffect > 0");
break;
default:
searchCriteria.append(StringFormat(" AND items.itemtype = %i", Type));
}
switch(ItemStat) {
case STAT_AC:
searchCriteria.append(" AND items.ac > 0");
searchValues.append(", items.ac");
switch (item_type) {
case 0xFFFFFFFF:
break;
case STAT_AGI:
searchCriteria.append(" AND items.aagi > 0");
searchValues.append(", items.aagi");
case 0:
// 1H Slashing
search_criteria.append(" AND items.itemtype = 0 AND damage > 0");
break;
case STAT_CHA:
searchCriteria.append(" AND items.acha > 0");
searchValues.append(", items.acha");
case 31:
search_criteria.append(" AND items.itemclass = 2");
break;
case STAT_DEX:
searchCriteria.append(" AND items.adex > 0");
searchValues.append(", items.adex");
case 46:
search_criteria.append(" AND items.spellid > 0 AND items.spellid < 65000");
break;
case STAT_INT:
searchCriteria.append(" AND items.aint > 0");
searchValues.append(", items.aint");
case 47:
search_criteria.append(" AND items.spellid = 998");
break;
case STAT_STA:
searchCriteria.append(" AND items.asta > 0");
searchValues.append(", items.asta");
case 48:
search_criteria.append(" AND items.spellid >= 1298 AND items.spellid <= 1307");
break;
case STAT_STR:
searchCriteria.append(" AND items.astr > 0");
searchValues.append(", items.astr");
break;
case STAT_WIS:
searchCriteria.append(" AND items.awis > 0");
searchValues.append(", items.awis");
break;
case STAT_COLD:
searchCriteria.append(" AND items.cr > 0");
searchValues.append(", items.cr");
break;
case STAT_DISEASE:
searchCriteria.append(" AND items.dr > 0");
searchValues.append(", items.dr");
break;
case STAT_FIRE:
searchCriteria.append(" AND items.fr > 0");
searchValues.append(", items.fr");
break;
case STAT_MAGIC:
searchCriteria.append(" AND items.mr > 0");
searchValues.append(", items.mr");
break;
case STAT_POISON:
searchCriteria.append(" AND items.pr > 0");
searchValues.append(", items.pr");
break;
case STAT_HP:
searchCriteria.append(" AND items.hp > 0");
searchValues.append(", items.hp");
break;
case STAT_MANA:
searchCriteria.append(" AND items.mana > 0");
searchValues.append(", items.mana");
break;
case STAT_ENDURANCE:
searchCriteria.append(" AND items.endur > 0");
searchValues.append(", items.endur");
break;
case STAT_ATTACK:
searchCriteria.append(" AND items.attack > 0");
searchValues.append(", items.attack");
break;
case STAT_HP_REGEN:
searchCriteria.append(" AND items.regen > 0");
searchValues.append(", items.regen");
break;
case STAT_MANA_REGEN:
searchCriteria.append(" AND items.manaregen > 0");
searchValues.append(", items.manaregen");
break;
case STAT_HASTE:
searchCriteria.append(" AND items.haste > 0");
searchValues.append(", items.haste");
break;
case STAT_DAMAGE_SHIELD:
searchCriteria.append(" AND items.damageshield > 0");
searchValues.append(", items.damageshield");
case 49:
search_criteria.append(" AND items.focuseffect > 0");
break;
default:
searchValues.append(", 0");
search_criteria.append(StringFormat(" AND items.itemtype = %i", item_type));
}
switch (item_stat) {
case STAT_AC:
search_criteria.append(" AND items.ac > 0");
search_values.append(", items.ac");
break;
case STAT_AGI:
search_criteria.append(" AND items.aagi > 0");
search_values.append(", items.aagi");
break;
case STAT_CHA:
search_criteria.append(" AND items.acha > 0");
search_values.append(", items.acha");
break;
case STAT_DEX:
search_criteria.append(" AND items.adex > 0");
search_values.append(", items.adex");
break;
case STAT_INT:
search_criteria.append(" AND items.aint > 0");
search_values.append(", items.aint");
break;
case STAT_STA:
search_criteria.append(" AND items.asta > 0");
search_values.append(", items.asta");
break;
case STAT_STR:
search_criteria.append(" AND items.astr > 0");
search_values.append(", items.astr");
break;
case STAT_WIS:
search_criteria.append(" AND items.awis > 0");
search_values.append(", items.awis");
break;
case STAT_COLD:
search_criteria.append(" AND items.cr > 0");
search_values.append(", items.cr");
break;
case STAT_DISEASE:
search_criteria.append(" AND items.dr > 0");
search_values.append(", items.dr");
break;
case STAT_FIRE:
search_criteria.append(" AND items.fr > 0");
search_values.append(", items.fr");
break;
case STAT_MAGIC:
search_criteria.append(" AND items.mr > 0");
search_values.append(", items.mr");
break;
case STAT_POISON:
search_criteria.append(" AND items.pr > 0");
search_values.append(", items.pr");
break;
case STAT_HP:
search_criteria.append(" AND items.hp > 0");
search_values.append(", items.hp");
break;
case STAT_MANA:
search_criteria.append(" AND items.mana > 0");
search_values.append(", items.mana");
break;
case STAT_ENDURANCE:
search_criteria.append(" AND items.endur > 0");
search_values.append(", items.endur");
break;
case STAT_ATTACK:
search_criteria.append(" AND items.attack > 0");
search_values.append(", items.attack");
break;
case STAT_HP_REGEN:
search_criteria.append(" AND items.regen > 0");
search_values.append(", items.regen");
break;
case STAT_MANA_REGEN:
search_criteria.append(" AND items.manaregen > 0");
search_values.append(", items.manaregen");
break;
case STAT_HASTE:
search_criteria.append(" AND items.haste > 0");
search_values.append(", items.haste");
break;
case STAT_DAMAGE_SHIELD:
search_criteria.append(" AND items.damageshield > 0");
search_values.append(", items.damageshield");
break;
default:
search_values.append(", 0");
break;
}
std::string query = StringFormat("SELECT %s, SUM(charges), items.stackable "
"FROM trader, items %s GROUP BY items.id, charges, char_id LIMIT %i",
searchValues.c_str(), searchCriteria.c_str(), RuleI(Bazaar, MaxSearchResults));
auto results = database.QueryDatabase(query);
if (!results.Success()) {
std::string query = StringFormat(
"SELECT %s, SUM(charges), items.stackable "
"FROM trader, items %s GROUP BY items.id, charges, char_id LIMIT %i",
search_values.c_str(),
search_criteria.c_str(),
RuleI(Bazaar, MaxSearchResults)
);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
return;
}
LogTrading("SRCH: [{}]", query.c_str());
int Size = 0;
uint32 ID = 0;
if (results.RowCount() == static_cast<unsigned long>(RuleI(Bazaar, MaxSearchResults)))
Message(Chat::Yellow, "Your search reached the limit of %i results. Please narrow your search down by selecting more options.",
RuleI(Bazaar, MaxSearchResults));
if(results.RowCount() == 0) {
auto outapp2 = new EQApplicationPacket(OP_BazaarSearch, sizeof(BazaarReturnDone_Struct));
BazaarReturnDone_Struct *brds = (BazaarReturnDone_Struct *)outapp2->pBuffer;
brds->TraderID = ID;
brds->Type = BazaarSearchDone;
brds->Unknown008 = 0xFFFFFFFF;
brds->Unknown012 = 0xFFFFFFFF;
brds->Unknown016 = 0xFFFFFFFF;
this->QueuePacket(outapp2);
safe_delete(outapp2);
return;
}
Size = results.RowCount() * sizeof(BazaarSearchResults_Struct);
auto buffer = new uchar[Size];
uchar *bufptr = buffer;
memset(buffer, 0, Size);
LogTrading("SRCH: [{}]", query.c_str());
int Action = BazaarSearchResults;
uint32 Cost = 0;
int32 SerialNumber = 0;
char temp_buffer[64] = {0};
int Count = 0;
uint32 StatValue = 0;
int Size = 0;
uint32 ID = 0;
for (auto row = results.begin(); row != results.end(); ++row) {
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Action);
Count = atoi(row[0]);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Count);
SerialNumber = atoi(row[3]);
VARSTRUCT_ENCODE_TYPE(int32, bufptr, SerialNumber);
Client *Trader2 = entity_list.GetClientByCharID(atoi(row[1]));
if (Trader2) {
ID = Trader2->GetID();
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, ID);
} else {
LogTrading("Unable to find trader: [{}]\n", atoi(row[1]));
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, 0);
}
Cost = atoi(row[5]);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Cost);
StatValue = atoi(row[8]);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, StatValue);
bool Stackable = atoi(row[10]);
if (Stackable) {
int Charges = atoi(row[9]);
sprintf(temp_buffer, "%s(%i)", row[7], Charges);
} else
sprintf(temp_buffer, "%s(%i)", row[7], Count);
if (results.RowCount() == static_cast<unsigned long>(RuleI(Bazaar, MaxSearchResults))) {
Message(
Chat::Yellow,
"Your search reached the limit of %i results. Please narrow your search down by selecting more options.",
RuleI(Bazaar, MaxSearchResults));
}
memcpy(bufptr, &temp_buffer, strlen(temp_buffer));
if (results.RowCount() == 0) {
auto outapp2 = new EQApplicationPacket(OP_BazaarSearch, sizeof(BazaarReturnDone_Struct));
BazaarReturnDone_Struct *brds = (BazaarReturnDone_Struct *) outapp2->pBuffer;
brds->TraderID = ID;
brds->Type = BazaarSearchDone;
brds->Unknown008 = 0xFFFFFFFF;
brds->Unknown012 = 0xFFFFFFFF;
brds->Unknown016 = 0xFFFFFFFF;
this->QueuePacket(outapp2);
safe_delete(outapp2);
return;
}
bufptr += 64;
Size = results.RowCount() * sizeof(BazaarSearchResults_Struct);
auto buffer = new uchar[Size];
uchar *bufptr = buffer;
memset(buffer, 0, Size);
// Extra fields for SoD+
//
if (Trader2)
sprintf(temp_buffer, "%s", Trader2->GetName());
else
sprintf(temp_buffer, "Unknown");
int Action = BazaarSearchResults;
uint32 Cost = 0;
int32 SerialNumber = 0;
char temp_buffer[64] = {0};
int Count = 0;
uint32 StatValue = 0;
memcpy(bufptr, &temp_buffer, strlen(temp_buffer));
for (auto row = results.begin(); row != results.end(); ++row) {
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Action);
Count = atoi(row[0]);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Count);
SerialNumber = atoi(row[3]);
VARSTRUCT_ENCODE_TYPE(int32, bufptr, SerialNumber);
Client *Trader2 = entity_list.GetClientByCharID(atoi(row[1]));
if (Trader2) {
ID = Trader2->GetID();
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, ID);
}
else {
LogTrading("Unable to find trader: [{}]\n", atoi(row[1]));
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, 0);
}
Cost = atoi(row[5]);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Cost);
StatValue = atoi(row[8]);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, StatValue);
bool Stackable = atoi(row[10]);
if (Stackable) {
int Charges = atoi(row[9]);
sprintf(temp_buffer, "%s(%i)", row[7], Charges);
}
else {
sprintf(temp_buffer, "%s(%i)", row[7], Count);
}
bufptr += 64;
memcpy(bufptr, &temp_buffer, strlen(temp_buffer));
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, atoi(row[1])); // ItemID
}
bufptr += 64;
auto outapp = new EQApplicationPacket(OP_BazaarSearch, Size);
// Extra fields for SoD+
//
if (Trader2) {
sprintf(temp_buffer, "%s", Trader2->GetName());
}
else {
sprintf(temp_buffer, "Unknown");
}
memcpy(outapp->pBuffer, buffer, Size);
memcpy(bufptr, &temp_buffer, strlen(temp_buffer));
this->QueuePacket(outapp);
bufptr += 64;
safe_delete(outapp);
safe_delete_array(buffer);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, atoi(row[1])); // ItemID
}
auto outapp2 = new EQApplicationPacket(OP_BazaarSearch, sizeof(BazaarReturnDone_Struct));
BazaarReturnDone_Struct *brds = (BazaarReturnDone_Struct *)outapp2->pBuffer;
auto outapp = new EQApplicationPacket(OP_BazaarSearch, Size);
brds->TraderID = ID;
brds->Type = BazaarSearchDone;
memcpy(outapp->pBuffer, buffer, Size);
brds->Unknown008 = 0xFFFFFFFF;
brds->Unknown012 = 0xFFFFFFFF;
brds->Unknown016 = 0xFFFFFFFF;
this->QueuePacket(outapp);
this->QueuePacket(outapp2);
safe_delete(outapp);
safe_delete_array(buffer);
safe_delete(outapp2);
auto outapp2 = new EQApplicationPacket(OP_BazaarSearch, sizeof(BazaarReturnDone_Struct));
BazaarReturnDone_Struct *brds = (BazaarReturnDone_Struct *) outapp2->pBuffer;
brds->TraderID = ID;
brds->Type = BazaarSearchDone;
brds->Unknown008 = 0xFFFFFFFF;
brds->Unknown012 = 0xFFFFFFFF;
brds->Unknown016 = 0xFFFFFFFF;
this->QueuePacket(outapp2);
safe_delete(outapp2);
}
static void UpdateTraderCustomerItemsAdded(uint32 CustomerID, TraderCharges_Struct* gis, uint32 ItemID) {
+19 -13
View File
@@ -24,6 +24,7 @@
#include "entity.h"
#include "mob.h"
#include "trap.h"
#include "../common/repositories/criteria/content_filter_criteria.h"
/*
@@ -104,7 +105,7 @@ bool Trap::Process()
reset_timer.Disable();
charid = 0;
}
if (respawn_timer.Enabled() && respawn_timer.Check())
{
detected = false;
@@ -162,7 +163,7 @@ void Trap::Trigger(Mob* trigger)
for (i = 0; i < effectvalue2; i++)
{
if ((tmp = database.LoadNPCTypesData(effectvalue)))
if ((tmp = content_db.LoadNPCTypesData(effectvalue)))
{
auto randomOffset = glm::vec4(zone->random.Int(-5, 5),zone->random.Int(-5, 5),zone->random.Int(-5, 5), zone->random.Int(0, 249));
auto spawnPosition = randomOffset + glm::vec4(m_Position, 0.0f);
@@ -187,7 +188,7 @@ void Trap::Trigger(Mob* trigger)
for (i = 0; i < effectvalue2; i++)
{
if ((tmp = database.LoadNPCTypesData(effectvalue)))
if ((tmp = content_db.LoadNPCTypesData(effectvalue)))
{
auto randomOffset = glm::vec4(zone->random.Int(-2, 2), zone->random.Int(-2, 2), zone->random.Int(-2, 2), zone->random.Int(0, 249));
auto spawnPosition = randomOffset + glm::vec4(m_Position, 0.0f);
@@ -225,13 +226,13 @@ void Trap::Trigger(Mob* trigger)
safe_delete(outapp);
}
}
if (trigger && trigger->IsClient())
{
trigger->CastToClient()->trapid = trap_id;
charid = trigger->CastToClient()->CharacterID();
}
bool update = false;
if (despawn_when_triggered)
{
@@ -242,16 +243,16 @@ void Trap::Trigger(Mob* trigger)
{
reset_timer.Start(5000);
}
if (triggered_number > 0)
++times_triggered;
if (triggered_number > 0 && triggered_number <= times_triggered)
{
Log(Logs::General, Logs::Traps, "Triggered number for trap %d reached. %d/%d", trap_id, times_triggered, triggered_number);
update = true;
}
if (update)
{
UpdateTrap();
@@ -290,7 +291,7 @@ Trap* EntityList::FindNearbyTrap(Mob* searcher, float max_dist, float &trap_curd
}
else
trap_curdist = INVALID_INDEX;
return current_trap;
}
@@ -399,9 +400,14 @@ void EntityList::ClearTrapPointers()
bool ZoneDatabase::LoadTraps(const char* zonename, int16 version) {
std::string query = StringFormat("SELECT id, x, y, z, effect, effectvalue, effectvalue2, skill, "
std::string query = StringFormat(
"SELECT id, x, y, z, effect, effectvalue, effectvalue2, skill, "
"maxzdiff, radius, chance, message, respawn_time, respawn_var, level, "
"`group`, triggered_number, despawn_when_triggered, undetectable FROM traps WHERE zone='%s' AND version=%u", zonename, version);
"`group`, triggered_number, despawn_when_triggered, undetectable FROM traps WHERE zone='%s' AND version=%u %s",
zonename,
version,
ContentFilterCriteria::apply().c_str()
);
auto results = QueryDatabase(query);
if (!results.Success()) {
@@ -452,7 +458,7 @@ void Trap::CreateHiddenTrigger()
if(hiddenTrigger)
return;
const NPCType *base_type = database.LoadNPCTypesData(500);
const NPCType *base_type = content_db.LoadNPCTypesData(500);
auto make_npc = new NPCType;
memcpy(make_npc, base_type, sizeof(NPCType));
make_npc->max_hp = 100000;
@@ -557,6 +563,6 @@ void Trap::UpdateTrap(bool respawn, bool repopnow)
charid = 0;
if (respawn)
{
database.SetTrapData(this, repopnow);
content_db.SetTrapData(this, repopnow);
}
}
+33 -40
View File
@@ -561,62 +561,54 @@ void Mob::StopNavigation() {
mMovementManager->StopNavigation(this);
}
void NPC::AssignWaypoints(int32 grid, int start_wp)
void NPC::AssignWaypoints(int32 grid_id, int start_wp)
{
if (grid == 0)
if (grid_id == 0)
return; // grid ID 0 not supported
if (grid < 0) {
if (grid_id < 0) {
// Allow setting negative grid values for pausing pathing
this->CastToNPC()->SetGrid(grid);
this->CastToNPC()->SetGrid(grid_id);
return;
}
Waypoints.clear();
roamer = false;
// Retrieve the wander and pause types for this grid
std::string query = StringFormat("SELECT `type`, `type2` FROM `grid` WHERE `id` = %i AND `zoneid` = %i", grid,
zone->GetZoneID());
auto results = database.QueryDatabase(query);
if (!results.Success()) {
auto grid_entry = GridRepository::GetGrid(zone->zone_grids, grid_id);
if (grid_entry.id == 0) {
return;
}
if (results.RowCount() == 0)
return;
wandertype = grid_entry.type;
pausetype = grid_entry.type2;
auto row = results.begin();
wandertype = atoi(row[0]);
pausetype = atoi(row[1]);
SetGrid(grid); // Assign grid number
// Retrieve all waypoints for this grid
query = StringFormat("SELECT `x`,`y`,`z`,`pause`,`heading`, `centerpoint` "
"FROM grid_entries WHERE `gridid` = %i AND `zoneid` = %i "
"ORDER BY `number`", grid, zone->GetZoneID());
results = database.QueryDatabase(query);
if (!results.Success()) {
return;
}
SetGrid(grid_id); // Assign grid number
roamer = true;
max_wp = 0; // Initialize it; will increment it for each waypoint successfully added to the list
for (auto row = results.begin(); row != results.end(); ++row, ++max_wp)
{
wplist newwp;
newwp.index = max_wp;
newwp.x = atof(row[0]);
newwp.y = atof(row[1]);
newwp.z = atof(row[2]);
for (auto &entry : zone->zone_grid_entries) {
if (entry.gridid == grid_id) {
wplist new_waypoint{};
new_waypoint.index = max_wp;
new_waypoint.x = entry.x;
new_waypoint.y = entry.y;
new_waypoint.z = entry.z;
new_waypoint.pause = entry.pause;
new_waypoint.heading = entry.heading;
new_waypoint.centerpoint = entry.centerpoint;
newwp.pause = atoi(row[3]);
newwp.heading = atof(row[4]);
newwp.centerpoint = atobool(row[5]);
Waypoints.push_back(newwp);
LogPathing(
"Loading Grid [{}] number [{}] name [{}]",
grid_id,
entry.number,
GetCleanName()
);
Waypoints.push_back(new_waypoint);
max_wp++;
}
}
cur_wp = start_wp;
@@ -628,8 +620,9 @@ void NPC::AssignWaypoints(int32 grid, int start_wp)
patrol = cur_wp;
}
if (wandertype == GridRandom10 || wandertype == GridRandom || wandertype == GridRand5LoS)
if (wandertype == GridRandom10 || wandertype == GridRandom || wandertype == GridRand5LoS) {
CalculateNewWaypoint();
}
}
@@ -737,7 +730,7 @@ void Mob::FixZ(int32 z_find_offset /*= 5*/, bool fix_client_z /*= false*/) {
if (IsClient() && !fix_client_z) {
return;
}
if (flymode == GravityBehavior::Flying) {
return;
}
@@ -1148,7 +1141,7 @@ int ZoneDatabase::GetRandomWaypointLocFromGrid(glm::vec4 &loc, uint16 zoneid, in
std::string query = StringFormat("SELECT `x`,`y`,`z`,`heading` "
"FROM grid_entries WHERE `gridid` = %i AND `zoneid` = %u ORDER BY `number`", grid, zone->GetZoneID());
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
Log(Logs::General, Logs::Error, "MySQL Error while trying get random waypoint loc from grid %i in zoneid %u; %s", grid, zoneid, results.ErrorMessage().c_str());
return 0;
+16 -16
View File
@@ -584,7 +584,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
case ServerOP_ZonePlayer: {
ServerZonePlayer_Struct* szp = (ServerZonePlayer_Struct*)pack->pBuffer;
Client* client = entity_list.GetClientByName(szp->name);
printf("Zoning %s to %s(%u) - %u\n", client != nullptr ? client->GetCleanName() : "Unknown", szp->zone, database.GetZoneID(szp->zone), szp->instance_id);
// printf("Zoning %s to %s(%u) - %u\n", client != nullptr ? client->GetCleanName() : "Unknown", szp->zone, ZoneID(szp->zone), szp->instance_id);
if (client) {
if (strcasecmp(szp->adminname, szp->name) == 0)
client->Message(Chat::White, "Zoning to: %s", szp->zone);
@@ -594,17 +594,17 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
SendEmoteMessage(szp->adminname, 0, 0, "Summoning %s to %s %1.1f, %1.1f, %1.1f", szp->name, szp->zone, szp->x_pos, szp->y_pos, szp->z_pos);
}
if (!szp->instance_id) {
client->MovePC(database.GetZoneID(szp->zone), szp->instance_id, szp->x_pos, szp->y_pos, szp->z_pos, client->GetHeading(), szp->ignorerestrictions, GMSummon);
client->MovePC(ZoneID(szp->zone), szp->instance_id, szp->x_pos, szp->y_pos, szp->z_pos, client->GetHeading(), szp->ignorerestrictions, GMSummon);
}
else {
if (database.GetInstanceID(client->CharacterID(), database.GetZoneID(szp->zone)) == 0) {
if (database.GetInstanceID(client->CharacterID(), ZoneID(szp->zone)) == 0) {
client->AssignToInstance(szp->instance_id);
client->MovePC(database.GetZoneID(szp->zone), szp->instance_id, szp->x_pos, szp->y_pos, szp->z_pos, client->GetHeading(), szp->ignorerestrictions, GMSummon);
client->MovePC(ZoneID(szp->zone), szp->instance_id, szp->x_pos, szp->y_pos, szp->z_pos, client->GetHeading(), szp->ignorerestrictions, GMSummon);
}
else {
client->RemoveFromInstance(database.GetInstanceID(client->CharacterID(), database.GetZoneID(szp->zone)));
client->RemoveFromInstance(database.GetInstanceID(client->CharacterID(), ZoneID(szp->zone)));
client->AssignToInstance(szp->instance_id);
client->MovePC(database.GetZoneID(szp->zone), szp->instance_id, szp->x_pos, szp->y_pos, szp->z_pos, client->GetHeading(), szp->ignorerestrictions, GMSummon);
client->MovePC(ZoneID(szp->zone), szp->instance_id, szp->x_pos, szp->y_pos, szp->z_pos, client->GetHeading(), szp->ignorerestrictions, GMSummon);
}
}
}
@@ -1951,7 +1951,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
CZMarqueeGroup_Struct* CZMS = (CZMarqueeGroup_Struct*) pack->pBuffer;
auto client_group = entity_list.GetGroupByID(CZMS->group_id);
std::string message = CZMS->message;
if (client_group) {
if (client_group) {
for (int member_index = 0; member_index < MAX_GROUP_MEMBERS; member_index++) {
if (client_group->members[member_index] && client_group->members[member_index]->IsClient()) {
auto group_member = client_group->members[member_index]->CastToClient();
@@ -1980,7 +1980,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
{
CZMarqueeGuild_Struct* CZMS = (CZMarqueeGuild_Struct*) pack->pBuffer;
std::string message = CZMS->message;
for (auto &client : entity_list.GetClientList()) {
for (auto &client : entity_list.GetClientList()) {
if (client.second->GuildID() > 0 && client.second->GuildID() == CZMS->guild_id) {
client.second->SendMarqueeMessage(CZMS->type, CZMS->priority, CZMS->fade_in, CZMS->fade_out, CZMS->duration, message);
}
@@ -2081,7 +2081,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
}
break;
}
case ServerOP_CZMoveInstancePlayer:
{
CZMoveInstancePlayer_Struct* CZMP = (CZMoveInstancePlayer_Struct*) pack->pBuffer;
@@ -2851,32 +2851,32 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
{
std::string hotfix_name = std::string((char*)pack->pBuffer);
LogInfo("Loading items");
if (!database.LoadItems(hotfix_name)) {
if (!content_db.LoadItems(hotfix_name)) {
LogError("Loading items failed!");
}
LogInfo("Loading npc faction lists");
if (!database.LoadNPCFactionLists(hotfix_name)) {
if (!content_db.LoadNPCFactionLists(hotfix_name)) {
LogError("Loading npcs faction lists failed!");
}
LogInfo("Loading loot tables");
if (!database.LoadLoot(hotfix_name)) {
if (!content_db.LoadLoot(hotfix_name)) {
LogError("Loading loot failed!");
}
LogInfo("Loading skill caps");
if (!database.LoadSkillCaps(std::string(hotfix_name))) {
if (!content_db.LoadSkillCaps(std::string(hotfix_name))) {
LogError("Loading skill caps failed!");
}
LogInfo("Loading spells");
if (!database.LoadSpells(hotfix_name, &SPDAT_RECORDS, &spells)) {
if (!content_db.LoadSpells(hotfix_name, &SPDAT_RECORDS, &spells)) {
LogError("Loading spells failed!");
}
LogInfo("Loading base data");
if (!database.LoadBaseData(hotfix_name)) {
if (!content_db.LoadBaseData(hotfix_name)) {
LogError("Loading base data failed!");
}
break;
@@ -3265,4 +3265,4 @@ void WorldServer::OnKeepAlive(EQ::Timer *t)
{
ServerPacket pack(ServerOP_KeepAlive, 0);
SendPacket(&pack);
}
}
+325 -196
View File
@@ -56,6 +56,8 @@
#include "npc_scale_manager.h"
#include "../common/data_verification.h"
#include "zone_reload.h"
#include "../common/repositories/criteria/content_filter_criteria.h"
#include "../common/repositories/content_flags_repository.h"
#include <time.h>
#include <ctime>
@@ -83,7 +85,7 @@ Zone* zone = 0;
void UpdateWindowTitle(char* iNewTitle);
bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
const char* zonename = database.GetZoneName(iZoneID);
const char* zonename = ZoneName(iZoneID);
if (iZoneID == 0 || zonename == 0)
return false;
@@ -156,7 +158,7 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
/**
* Set Shutdown timer
*/
uint32 shutdown_timer = static_cast<uint32>(database.getZoneShutDownDelay(zone->GetZoneID(), zone->GetInstanceVersion()));
uint32 shutdown_timer = static_cast<uint32>(content_db.getZoneShutDownDelay(zone->GetZoneID(), zone->GetInstanceVersion()));
zone->StartShutdownTimer(shutdown_timer);
/*
@@ -170,12 +172,15 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
//this really loads the objects into entity_list
bool Zone::LoadZoneObjects()
{
std::string query =
StringFormat("SELECT id, zoneid, xpos, ypos, zpos, heading, itemid, charges, objectname, type, icon, "
"unknown08, unknown10, unknown20, unknown24, unknown76, size, tilt_x, tilt_y, display_name "
"FROM object WHERE zoneid = %i AND (version = %u OR version = -1)",
zoneid, instanceversion);
auto results = database.QueryDatabase(query);
std::string query = StringFormat(
"SELECT id, zoneid, xpos, ypos, zpos, heading, itemid, charges, objectname, type, icon, "
"unknown08, unknown10, unknown20, unknown24, unknown76, size, tilt_x, tilt_y, display_name "
"FROM object WHERE zoneid = %i AND (version = %u OR version = -1) %s",
zoneid,
instanceversion,
ContentFilterCriteria::apply().c_str()
);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
LogError("Error Loading Objects from DB: [{}]",
results.ErrorMessage().c_str());
@@ -186,7 +191,7 @@ bool Zone::LoadZoneObjects()
for (auto row = results.begin(); row != results.end(); ++row) {
if (atoi(row[9]) == 0) {
// Type == 0 - Static Object
const char *shortname = database.GetZoneName(atoi(row[1]), false); // zoneid -> zone_shortname
const char *shortname = ZoneName(atoi(row[1]), false); // zoneid -> zone_shortname
if (!shortname)
continue;
@@ -262,6 +267,14 @@ bool Zone::LoadZoneObjects()
data.tilt_y = atof(row[18]);
data.unknown084 = 0;
glm::vec3 position;
position.x = data.x;
position.y = data.y;
position.z = data.z;
data.z = zone->zonemap->FindBestZ(position, nullptr);
EQ::ItemInstance *inst = nullptr;
// FatherNitwit: this dosent seem to work...
// tradeskill containers do not have an itemid of 0... at least what I am seeing
@@ -302,7 +315,7 @@ bool Zone::LoadGroundSpawns() {
memset(&groundspawn, 0, sizeof(groundspawn));
int gsindex=0;
LogInfo("Loading Ground Spawns from DB");
database.LoadGroundSpawns(zoneid, GetInstanceVersion(), &groundspawn);
content_db.LoadGroundSpawns(zoneid, GetInstanceVersion(), &groundspawn);
uint32 ix=0;
char* name = nullptr;
uint32 gsnumber=0;
@@ -337,7 +350,7 @@ void Zone::DumpMerchantList(uint32 npcid) {
for (tmp_itr = tmp_merlist.begin(); tmp_itr != tmp_merlist.end(); ++tmp_itr) {
ml = *tmp_itr;
LogInventory("slot[{}] Orig[{}] Item[{}] Charges[{}]", ml.slot, ml.origslot, ml.item, ml.charges);
}
}
@@ -374,7 +387,7 @@ int Zone::SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charg
for (tmp_itr = tmp_merlist.begin(); tmp_itr != tmp_merlist.end(); ++tmp_itr) {
ml = *tmp_itr;
if (ml.item == item) {
found = true;
LogInventory("Item found in temp list at [{}] with [{}] charges", ml.origslot, ml.charges);
@@ -398,11 +411,11 @@ int Zone::SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charg
ml.charges = charges;
LogInventory("new charges is [{}] charges", ml.charges);
}
if (!ml.origslot) {
ml.origslot = ml.slot;
}
if (charges > 0) {
database.SaveMerchantTemp(npcid, ml.origslot, item, ml.charges);
tmp_merlist.push_back(ml);
@@ -428,7 +441,7 @@ int Zone::SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charg
for (tmp_itr = tmp_merlist.begin(); tmp_itr != tmp_merlist.end(); ++tmp_itr) {
ml3 = *tmp_itr;
slots.push_back(ml3.origslot);
}
}
slots.sort();
std::list<int>::const_iterator slots_itr;
uint32 first_empty_slot = 0;
@@ -441,7 +454,7 @@ int Zone::SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charg
}
++idx;
}
}
first_empty_slot = idx;
@@ -450,7 +463,7 @@ int Zone::SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charg
for (tmp_itr = tmp_merlist.begin(); tmp_itr != tmp_merlist.end(); ++tmp_itr) {
ml3 = *tmp_itr;
slots.push_back(ml3.slot);
}
}
slots.sort();
uint32 first_empty_mslot=0;
idx = temp_slot_index;
@@ -462,7 +475,7 @@ int Zone::SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charg
}
++idx;
}
}
first_empty_mslot = idx;
@@ -496,120 +509,189 @@ uint32 Zone::GetTempMerchantQuantity(uint32 NPCID, uint32 Slot) {
return 0;
}
void Zone::LoadTempMerchantData() {
void Zone::LoadTempMerchantData()
{
LogInfo("Loading Temporary Merchant Lists");
std::string query = StringFormat(
"SELECT "
"DISTINCT ml.npcid, "
"ml.slot, "
"ml.charges, "
"ml.itemid "
"FROM "
"merchantlist_temp ml, "
"spawnentry se, "
"spawn2 s2 "
"WHERE "
"ml.npcid = se.npcid "
"AND se.spawngroupid = s2.spawngroupid "
"AND s2.zone = '%s' AND s2.version = %i "
"ORDER BY ml.slot ", GetShortName(), GetInstanceVersion());
auto results = database.QueryDatabase(query);
if (!results.Success()) {
return;
}
std::map<uint32, std::list<TempMerchantList> >::iterator cur;
uint32 npcid = 0;
auto results = content_db.QueryDatabase(
fmt::format(
SQL(
SELECT
DISTINCT npc_types.id
FROM
npc_types
JOIN spawnentry ON spawnentry.npcID = npc_types.id
JOIN spawn2 ON spawn2.spawngroupID = spawnentry.spawngroupID
WHERE
spawn2.zone = '{}'
AND spawn2.version = {}
),
GetShortName(),
GetInstanceVersion()
)
);
std::vector<std::string> npc_ids;
for (auto row = results.begin(); row != results.end(); ++row) {
TempMerchantList ml;
ml.npcid = atoul(row[0]);
if (npcid != ml.npcid){
cur = tmpmerchanttable.find(ml.npcid);
if (cur == tmpmerchanttable.end()) {
std::list<TempMerchantList> empty;
tmpmerchanttable[ml.npcid] = empty;
cur = tmpmerchanttable.find(ml.npcid);
}
npcid = ml.npcid;
}
ml.slot = atoul(row[1]);
ml.charges = atoul(row[2]);
ml.item = atoul(row[3]);
ml.origslot = ml.slot;
cur->second.push_back(ml);
npc_ids.push_back(row[0]);
}
results = database.QueryDatabase(
fmt::format(
SQL(
SELECT
npcid,
slot,
charges,
itemid
FROM merchantlist_temp
WHERE npcid IN ({})
),
implode(", ", npc_ids)
)
);
std::map<uint32, std::list<TempMerchantList> >::iterator temp_merchant_table_entry;
uint32 npc_id = 0;
for (auto row = results.begin(); row != results.end(); ++row) {
TempMerchantList temp_merchant_list;
temp_merchant_list.npcid = atoul(row[0]);
if (npc_id != temp_merchant_list.npcid) {
temp_merchant_table_entry = tmpmerchanttable.find(temp_merchant_list.npcid);
if (temp_merchant_table_entry == tmpmerchanttable.end()) {
std::list<TempMerchantList> empty;
tmpmerchanttable[temp_merchant_list.npcid] = empty;
temp_merchant_table_entry = tmpmerchanttable.find(temp_merchant_list.npcid);
}
npc_id = temp_merchant_list.npcid;
}
temp_merchant_list.slot = atoul(row[1]);
temp_merchant_list.charges = atoul(row[2]);
temp_merchant_list.item = atoul(row[3]);
temp_merchant_list.origslot = temp_merchant_list.slot;
LogMerchants(
"[LoadTempMerchantData] Loading merchant temp items npc_id [{}] slot [{}] charges [{}] item [{}] origslot [{}]",
npc_id,
temp_merchant_list.slot,
temp_merchant_list.charges,
temp_merchant_list.item,
temp_merchant_list.origslot
);
temp_merchant_table_entry->second.push_back(temp_merchant_list);
}
pQueuedMerchantsWorkID = 0;
}
void Zone::LoadNewMerchantData(uint32 merchantid) {
std::list<MerchantList> merlist;
std::string query = StringFormat("SELECT item, slot, faction_required, level_required, alt_currency_cost, "
"classes_required, probability FROM merchantlist WHERE merchantid=%d ORDER BY slot", merchantid);
auto results = database.QueryDatabase(query);
std::string query = fmt::format(
SQL(
SELECT
item,
slot,
faction_required,
level_required,
alt_currency_cost,
classes_required,
probability
FROM
merchantlist
WHERE
merchantid = {}
{}
ORDER BY
slot
),
merchantid,
ContentFilterCriteria::apply()
);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
return;
}
}
for(auto row = results.begin(); row != results.end(); ++row) {
MerchantList ml;
ml.id = merchantid;
ml.item = atoul(row[0]);
ml.slot = atoul(row[1]);
ml.faction_required = atoul(row[2]);
ml.level_required = atoul(row[3]);
ml.alt_currency_cost = atoul(row[4]);
ml.classes_required = atoul(row[5]);
ml.probability = atoul(row[6]);
merlist.push_back(ml);
}
for (auto row = results.begin(); row != results.end(); ++row) {
MerchantList ml;
ml.id = merchantid;
ml.item = atoul(row[0]);
ml.slot = atoul(row[1]);
ml.faction_required = atoul(row[2]);
ml.level_required = atoul(row[3]);
ml.alt_currency_cost = atoul(row[4]);
ml.classes_required = atoul(row[5]);
ml.probability = atoul(row[6]);
merlist.push_back(ml);
}
merchanttable[merchantid] = merlist;
merchanttable[merchantid] = merlist;
}
void Zone::GetMerchantDataForZoneLoad() {
LogInfo("Loading Merchant Lists");
std::string query = StringFormat(
"SELECT "
"DISTINCT ml.merchantid, "
"ml.slot, "
"ml.item, "
"ml.faction_required, "
"ml.level_required, "
"ml.alt_currency_cost, "
"ml.classes_required, "
"ml.probability "
"FROM "
"merchantlist AS ml, "
"npc_types AS nt, "
"spawnentry AS se, "
"spawn2 AS s2 "
"WHERE nt.merchant_id = ml.merchantid AND nt.id = se.npcid "
"AND se.spawngroupid = s2.spawngroupid AND s2.zone = '%s' AND s2.version = %i "
"ORDER BY ml.slot ", GetShortName(), GetInstanceVersion());
auto results = database.QueryDatabase(query);
std::map<uint32, std::list<MerchantList> >::iterator cur;
uint32 npcid = 0;
std::string query = fmt::format(
SQL (
SELECT
DISTINCT merchantlist.merchantid,
merchantlist.slot,
merchantlist.item,
merchantlist.faction_required,
merchantlist.level_required,
merchantlist.alt_currency_cost,
merchantlist.classes_required,
merchantlist.probability
FROM
merchantlist,
npc_types,
spawnentry,
spawn2
WHERE
npc_types.merchant_id = merchantlist.merchantid
AND npc_types.id = spawnentry.npcid
AND spawnentry.spawngroupid = spawn2.spawngroupid
AND spawn2.zone = '{}'
AND spawn2.version = {}
{}
ORDER BY
merchantlist.slot
),
GetShortName(),
GetInstanceVersion(),
ContentFilterCriteria::apply("merchantlist")
);
auto results = content_db.QueryDatabase(query);
std::map<uint32, std::list<MerchantList> >::iterator merchant_list;
uint32 npc_id = 0;
if (results.RowCount() == 0) {
LogDebug("No Merchant Data found for [{}]", GetShortName());
return;
}
for (auto row = results.begin(); row != results.end(); ++row) {
MerchantList ml;
ml.id = atoul(row[0]);
if (npcid != ml.id) {
cur = merchanttable.find(ml.id);
if (cur == merchanttable.end()) {
MerchantList merchant_list_entry{};
merchant_list_entry.id = atoul(row[0]);
if (npc_id != merchant_list_entry.id) {
merchant_list = merchanttable.find(merchant_list_entry.id);
if (merchant_list == merchanttable.end()) {
std::list<MerchantList> empty;
merchanttable[ml.id] = empty;
cur = merchanttable.find(ml.id);
merchanttable[merchant_list_entry.id] = empty;
merchant_list = merchanttable.find(merchant_list_entry.id);
}
npcid = ml.id;
npc_id = merchant_list_entry.id;
}
auto iter = cur->second.begin();
auto iter = merchant_list->second.begin();
bool found = false;
while (iter != cur->second.end()) {
if ((*iter).item == ml.id) {
while (iter != merchant_list->second.end()) {
if ((*iter).item == merchant_list_entry.id) {
found = true;
break;
}
@@ -620,14 +702,15 @@ void Zone::GetMerchantDataForZoneLoad() {
continue;
}
ml.slot = atoul(row[1]);
ml.item = atoul(row[2]);
ml.faction_required = atoul(row[3]);
ml.level_required = atoul(row[4]);
ml.alt_currency_cost = atoul(row[5]);
ml.classes_required = atoul(row[6]);
ml.probability = atoul(row[7]);
cur->second.push_back(ml);
merchant_list_entry.slot = atoul(row[1]);
merchant_list_entry.item = atoul(row[2]);
merchant_list_entry.faction_required = atoul(row[3]);
merchant_list_entry.level_required = atoul(row[4]);
merchant_list_entry.alt_currency_cost = atoul(row[5]);
merchant_list_entry.classes_required = atoul(row[6]);
merchant_list_entry.probability = atoul(row[7]);
merchant_list->second.push_back(merchant_list_entry);
}
}
@@ -820,7 +903,7 @@ void Zone::LoadZoneDoors(const char* zone, int16 version)
LogInfo("Loading doors for [{}] ", zone);
uint32 maxid;
int32 count = database.GetDoorsCount(&maxid, zone, version);
int32 count = content_db.GetDoorsCount(&maxid, zone, version);
if(count < 1) {
LogInfo("No doors loaded");
return;
@@ -828,7 +911,7 @@ void Zone::LoadZoneDoors(const char* zone, int16 version)
auto dlist = new Door[count];
if(!database.LoadDoors(count, dlist, zone, version)) {
if(!content_db.LoadDoors(count, dlist, zone, version)) {
LogError("Failed to load doors");
delete[] dlist;
return;
@@ -884,15 +967,14 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
pgraveyard_id = 0;
pgraveyard_zoneid = 0;
pMaxClients = 0;
pQueuedMerchantsWorkID = 0;
pvpzone = false;
if(database.GetServerType() == 1)
pvpzone = true;
database.GetZoneLongName(short_name, &long_name, file_name, &m_SafePoint.x, &m_SafePoint.y, &m_SafePoint.z, &pgraveyard_id, &pMaxClients);
content_db.GetZoneLongName(short_name, &long_name, file_name, &m_SafePoint.x, &m_SafePoint.y, &m_SafePoint.z, &pgraveyard_id, &pMaxClients);
if(graveyard_id() > 0)
{
LogDebug("Graveyard ID is [{}]", graveyard_id());
bool GraveYardLoaded = database.GetZoneGraveyard(graveyard_id(), &pgraveyard_zoneid, &m_Graveyard.x, &m_Graveyard.y, &m_Graveyard.z, &m_Graveyard.w);
bool GraveYardLoaded = content_db.GetZoneGraveyard(graveyard_id(), &pgraveyard_zoneid, &m_Graveyard.x, &m_Graveyard.y, &m_Graveyard.z, &m_Graveyard.w);
if (GraveYardLoaded) {
LogDebug("Loaded a graveyard for zone [{}]: graveyard zoneid is [{}] at [{}]", short_name, graveyard_zoneid(), to_string(m_Graveyard).c_str());
@@ -986,14 +1068,16 @@ bool Zone::Init(bool iStaticZone) {
SetStaticZone(iStaticZone);
//load the zone config file.
if (!LoadZoneCFG(zone->GetShortName(), zone->GetInstanceVersion())) // try loading the zone name...
LoadZoneCFG(zone->GetFileName(), zone->GetInstanceVersion()); // if that fails, try the file name, then load defaults
if (!LoadZoneCFG(zone->GetShortName(), zone->GetInstanceVersion())) { // try loading the zone name...
LoadZoneCFG(
zone->GetFileName(),
zone->GetInstanceVersion()
);
} // if that fails, try the file name, then load defaults
if(RuleManager::Instance()->GetActiveRulesetID() != default_ruleset)
{
if (RuleManager::Instance()->GetActiveRulesetID() != default_ruleset) {
std::string r_name = RuleManager::Instance()->GetRulesetName(&database, default_ruleset);
if(r_name.size() > 0)
{
if (r_name.size() > 0) {
RuleManager::Instance()->LoadRules(&database, r_name.c_str(), false);
}
}
@@ -1008,19 +1092,19 @@ bool Zone::Init(bool iStaticZone) {
}
LogInfo("Loading static zone points");
if (!database.LoadStaticZonePoints(&zone_point_list, short_name, GetInstanceVersion())) {
if (!content_db.LoadStaticZonePoints(&zone_point_list, short_name, GetInstanceVersion())) {
LogError("Loading static zone points failed");
return false;
}
LogInfo("Loading spawn groups");
if (!database.LoadSpawnGroups(short_name, GetInstanceVersion(), &spawn_group_list)) {
if (!content_db.LoadSpawnGroups(short_name, GetInstanceVersion(), &spawn_group_list)) {
LogError("Loading spawn groups failed");
return false;
}
LogInfo("Loading spawn2 points");
if (!database.PopulateZoneSpawnList(zoneid, spawn2_list, GetInstanceVersion()))
if (!content_db.PopulateZoneSpawnList(zoneid, spawn2_list, GetInstanceVersion()))
{
LogError("Loading spawn2 points failed");
return false;
@@ -1033,7 +1117,7 @@ bool Zone::Init(bool iStaticZone) {
}
LogInfo("Loading traps");
if (!database.LoadTraps(short_name, GetInstanceVersion()))
if (!content_db.LoadTraps(short_name, GetInstanceVersion()))
{
LogError("Loading traps failed");
return false;
@@ -1057,12 +1141,11 @@ bool Zone::Init(bool iStaticZone) {
LogInfo("Flushing old respawn timers");
database.QueryDatabase("DELETE FROM `respawn_times` WHERE (`start` + `duration`) < UNIX_TIMESTAMP(NOW())");
//load up the zone's doors (prints inside)
zone->LoadZoneDoors(zone->GetShortName(), zone->GetInstanceVersion());
zone->LoadZoneBlockedSpells(zone->GetZoneID());
//clear trader items if we are loading the bazaar
if(strncasecmp(short_name,"bazaar",6)==0) {
if (strncasecmp(short_name, "bazaar", 6) == 0) {
database.DeleteTraderItem(0);
database.DeleteBuyLines(0);
}
@@ -1075,7 +1158,7 @@ bool Zone::Init(bool iStaticZone) {
LoadAlternateAdvancement();
database.LoadGlobalLoot();
content_db.LoadGlobalLoot();
//Load merchant data
zone->GetMerchantDataForZoneLoad();
@@ -1096,10 +1179,11 @@ bool Zone::Init(bool iStaticZone) {
petition_list.ReadDatabase();
LogInfo("Loading timezone data");
zone->zone_time.setEQTimeZone(database.GetZoneTZ(zoneid, GetInstanceVersion()));
zone->zone_time.setEQTimeZone(content_db.GetZoneTZ(zoneid, GetInstanceVersion()));
LogInfo("Init Finished: ZoneID = [{}], Time Offset = [{}]", zoneid, zone->zone_time.getEQTimeZone());
LoadGrids();
LoadTickItems();
//MODDING HOOK FOR ZONE INIT
@@ -1113,13 +1197,13 @@ void Zone::ReloadStaticData() {
LogInfo("Reloading static zone points");
zone_point_list.Clear();
if (!database.LoadStaticZonePoints(&zone_point_list, GetShortName(), GetInstanceVersion())) {
if (!content_db.LoadStaticZonePoints(&zone_point_list, GetShortName(), GetInstanceVersion())) {
LogError("Loading static zone points failed");
}
LogInfo("Reloading traps");
entity_list.RemoveAllTraps();
if (!database.LoadTraps(GetShortName(), GetInstanceVersion()))
if (!content_db.LoadTraps(GetShortName(), GetInstanceVersion()))
{
LogError("Reloading traps failed");
}
@@ -1147,8 +1231,16 @@ void Zone::ReloadStaticData() {
zone->LoadNPCEmotes(&NPCEmoteList);
//load the zone config file.
if (!LoadZoneCFG(zone->GetShortName(), zone->GetInstanceVersion())) // try loading the zone name...
LoadZoneCFG(zone->GetFileName(), zone->GetInstanceVersion()); // if that fails, try the file name, then load defaults
if (!LoadZoneCFG(zone->GetShortName(), zone->GetInstanceVersion())) { // try loading the zone name...
LoadZoneCFG(
zone->GetFileName(),
zone->GetInstanceVersion()
);
} // if that fails, try the file name, then load defaults
content_service.SetExpansionContext();
ZoneStore::LoadContentFlags();
LogInfo("Zone Static Data Reloaded");
}
@@ -1159,19 +1251,44 @@ bool Zone::LoadZoneCFG(const char* filename, uint16 instance_id)
memset(&newzone_data, 0, sizeof(NewZone_Struct));
map_name = nullptr;
if(!database.GetZoneCFG(database.GetZoneID(filename), instance_id, &newzone_data, can_bind,
can_combat, can_levitate, can_castoutdoor, is_city, is_hotzone, allow_mercs, max_movement_update_range, zone_type, default_ruleset, &map_name))
{
if (!content_db.GetZoneCFG(
ZoneID(filename),
instance_id,
&newzone_data,
can_bind,
can_combat,
can_levitate,
can_castoutdoor,
is_city,
is_hotzone,
allow_mercs,
max_movement_update_range,
zone_type,
default_ruleset,
&map_name
)) {
// If loading a non-zero instance failed, try loading the default
if (instance_id != 0)
{
if (instance_id != 0) {
safe_delete_array(map_name);
if(!database.GetZoneCFG(database.GetZoneID(filename), 0, &newzone_data, can_bind, can_combat, can_levitate,
can_castoutdoor, is_city, is_hotzone, allow_mercs, max_movement_update_range, zone_type, default_ruleset, &map_name))
{
if (!content_db.GetZoneCFG(
ZoneID(filename),
0,
&newzone_data,
can_bind,
can_combat,
can_levitate,
can_castoutdoor,
is_city,
is_hotzone,
allow_mercs,
max_movement_update_range,
zone_type,
default_ruleset,
&map_name
)) {
LogError("Error loading the Zone Config");
return false;
}
}
}
}
@@ -1180,12 +1297,20 @@ bool Zone::LoadZoneCFG(const char* filename, uint16 instance_id)
strcpy(newzone_data.zone_long_name, GetLongName());
strcpy(newzone_data.zone_short_name2, GetShortName());
LogInfo("Successfully loaded Zone Config");
LogInfo(
"Successfully loaded Zone Config for Zone [{}] ({}) Version [{}] Instance ID [{}]",
GetShortName(),
GetLongName(),
GetInstanceVersion(),
instance_id
);
return true;
}
bool Zone::SaveZoneCFG() {
return database.SaveZoneCFG(GetZoneID(), GetInstanceVersion(), &newzone_data);
bool Zone::SaveZoneCFG()
{
return content_db.SaveZoneCFG(GetZoneID(), GetInstanceVersion(), &newzone_data);
}
void Zone::AddAuth(ServerZoneIncomingClient_Struct* szic) {
@@ -1290,8 +1415,6 @@ bool Zone::Process() {
EQ::InventoryProfile::CleanDirty();
LogSpawns("Running Zone::Process -> Spawn2::Process");
iterator.Reset();
while (iterator.MoreElements()) {
if (iterator.GetData()->Process()) {
@@ -1564,7 +1687,7 @@ bool Zone::HasWeather()
void Zone::StartShutdownTimer(uint32 set_time) {
if (set_time > autoshutdown_timer.GetRemainingTime()) {
if (set_time == (RuleI(Zone, AutoShutdownDelay))) {
set_time = static_cast<uint32>(database.getZoneShutDownDelay(GetZoneID(), GetInstanceVersion()));
set_time = static_cast<uint32>(content_db.getZoneShutDownDelay(GetZoneID(), GetInstanceVersion()));
}
autoshutdown_timer.SetTimer(set_time);
@@ -1616,29 +1739,6 @@ void Zone::ClearNPCTypeCache(int id) {
}
}
void Zone::RepopClose(const glm::vec4& client_position, uint32 repop_distance)
{
if (!Depop())
return;
LinkedListIterator<Spawn2*> iterator(spawn2_list);
iterator.Reset();
while (iterator.MoreElements()) {
iterator.RemoveCurrent();
}
quest_manager.ClearAllTimers();
if (!database.PopulateZoneSpawnListClose(zoneid, spawn2_list, GetInstanceVersion(), client_position, repop_distance))
LogDebug("Error in Zone::Repop: database.PopulateZoneSpawnList failed");
initgrids_timer.Start();
mod_repop();
}
void Zone::Repop(uint32 delay)
{
if (!Depop()) {
@@ -1658,8 +1758,21 @@ void Zone::Repop(uint32 delay)
quest_manager.ClearAllTimers();
if (!database.PopulateZoneSpawnList(zoneid, spawn2_list, GetInstanceVersion(), delay))
LogInfo("Loading spawn groups");
if (!content_db.LoadSpawnGroups(short_name, GetInstanceVersion(), &spawn_group_list)) {
LogError("Loading spawn groups failed");
}
LogInfo("Loading spawn conditions");
if (!spawn_conditions.LoadSpawnConditions(short_name, instanceid)) {
LogError("Loading spawn conditions failed, continuing without them");
}
if (!content_db.PopulateZoneSpawnList(zoneid, spawn2_list, GetInstanceVersion(), delay)) {
LogDebug("Error in Zone::Repop: database.PopulateZoneSpawnList failed");
}
LoadGrids();
initgrids_timer.Start();
@@ -1745,8 +1858,7 @@ ZonePoint* Zone::GetClosestZonePoint(const glm::vec3& location, uint32 to, Clien
{
ZonePoint* zp = iterator.GetData();
uint32 mask_test = client->ClientVersionBit();
if(!(zp->client_version_mask & mask_test))
{
if (!(zp->client_version_mask & mask_test)) {
iterator.Advance();
continue;
}
@@ -1787,7 +1899,7 @@ ZonePoint* Zone::GetClosestZonePoint(const glm::vec3& location, uint32 to, Clien
ZonePoint* Zone::GetClosestZonePoint(const glm::vec3& location, const char* to_name, Client* client, float max_distance) {
if(to_name == nullptr)
return GetClosestZonePointWithoutZone(location.x, location.y, location.z, client, max_distance);
return GetClosestZonePoint(location, database.GetZoneID(to_name), client, max_distance);
return GetClosestZonePoint(location, ZoneID(to_name), client, max_distance);
}
ZonePoint* Zone::GetClosestZonePointWithoutZone(float x, float y, float z, Client* client, float max_distance) {
@@ -1828,16 +1940,22 @@ ZonePoint* Zone::GetClosestZonePointWithoutZone(float x, float y, float z, Clien
return closest_zp;
}
bool ZoneDatabase::LoadStaticZonePoints(LinkedList<ZonePoint*>* zone_point_list, const char* zonename, uint32 version)
bool ZoneDatabase::LoadStaticZonePoints(LinkedList<ZonePoint *> *zone_point_list, const char *zonename, uint32 version)
{
zone_point_list->Clear();
zone->numzonepoints = 0;
std::string query = StringFormat("SELECT x, y, z, target_x, target_y, "
"target_z, target_zone_id, heading, target_heading, "
"number, target_instance, client_version_mask "
"FROM zone_points WHERE zone='%s' AND (version=%i OR version=-1) "
"ORDER BY number",
zonename, version);
std::string query = StringFormat(
"SELECT x, y, z, target_x, target_y, "
"target_z, target_zone_id, heading, target_heading, "
"number, target_instance, client_version_mask "
"FROM zone_points WHERE zone='%s' AND (version=%i OR version=-1) %s"
"ORDER BY number",
zonename,
version,
ContentFilterCriteria::apply().c_str()
);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
@@ -2018,10 +2136,10 @@ void Zone::SetGraveyard(uint32 zoneid, const glm::vec4& graveyardPosition) {
void Zone::LoadZoneBlockedSpells(uint32 zone_id)
{
if (!blocked_spells) {
zone_total_blocked_spells = database.GetBlockedSpellsCount(zone_id);
zone_total_blocked_spells = content_db.GetBlockedSpellsCount(zone_id);
if (zone_total_blocked_spells > 0) {
blocked_spells = new ZoneSpellsBlocked[zone_total_blocked_spells];
if (!database.LoadBlockedSpells(zone_total_blocked_spells, blocked_spells, zone_id)) {
if (!content_db.LoadBlockedSpells(zone_total_blocked_spells, blocked_spells, zone_id)) {
LogError(" Failed to load blocked spells");
ClearBlockedSpells();
}
@@ -2133,7 +2251,7 @@ void Zone::SetInstanceTimer(uint32 new_duration)
void Zone::LoadLDoNTraps()
{
const std::string query = "SELECT id, type, spell_id, skill, locked FROM ldon_trap_templates";
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
return;
}
@@ -2153,7 +2271,7 @@ void Zone::LoadLDoNTraps()
void Zone::LoadLDoNTrapEntries()
{
const std::string query = "SELECT id, trap_id FROM ldon_trap_entries";
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
return;
}
@@ -2194,7 +2312,7 @@ void Zone::LoadVeteranRewards()
"FROM veteran_reward_templates "
"WHERE reward_slot < 8 and claim_id > 0 "
"ORDER by claim_id, reward_slot";
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
return;
}
@@ -2239,7 +2357,7 @@ void Zone::LoadAlternateCurrencies()
AltCurrencyDefinition_Struct current_currency;
const std::string query = "SELECT id, item_id FROM alternate_currency";
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
return;
}
@@ -2286,7 +2404,7 @@ void Zone::DeleteQGlobal(std::string name, uint32 npcID, uint32 charID, uint32 z
void Zone::LoadAdventureFlavor()
{
const std::string query = "SELECT id, text FROM adventure_template_entry_flavor";
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
return;
}
@@ -2337,7 +2455,7 @@ void Zone::DoAdventureActions()
{
if(ds->assa_count >= RuleI(Adventure, NumberKillsForBossSpawn))
{
const NPCType* tmp = database.LoadNPCTypesData(ds->data_id);
const NPCType* tmp = content_db.LoadNPCTypesData(ds->data_id);
if(tmp)
{
NPC* npc = new NPC(tmp, nullptr, glm::vec4(ds->assa_x, ds->assa_y, ds->assa_z, ds->assa_h), GravityBehavior::Water);
@@ -2362,7 +2480,7 @@ void Zone::LoadNPCEmotes(LinkedList<NPC_Emote_Struct*>* NPCEmoteList)
NPCEmoteList->Clear();
const std::string query = "SELECT emoteid, event_, type, text FROM npc_emotes";
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
return;
}
@@ -2435,7 +2553,7 @@ uint32 Zone::GetSpawnKillCount(uint32 in_spawnid) {
void Zone::UpdateHotzone()
{
std::string query = StringFormat("SELECT hotzone FROM zone WHERE short_name = '%s'", GetShortName());
auto results = database.QueryDatabase(query);
auto results = content_db.QueryDatabase(query);
if (!results.Success())
return;
@@ -2533,6 +2651,17 @@ void Zone::SetQuestHotReloadQueued(bool in_quest_hot_reload_queued)
quest_hot_reload_queued = in_quest_hot_reload_queued;
}
void Zone::LoadGrids()
{
zone_grids = GridRepository::GetZoneGrids(GetZoneID());
zone_grid_entries = GridEntriesRepository::GetZoneGridEntries(GetZoneID());
}
Timer Zone::GetInitgridsTimer()
{
return initgrids_timer;
}
uint32 Zone::GetInstanceTimeRemaining() const
{
return instance_time_remaining;
+10 -6
View File
@@ -24,6 +24,10 @@
#include "../common/types.h"
#include "../common/random.h"
#include "../common/string_util.h"
#include "zonedb.h"
#include "zone_store.h"
#include "../common/repositories/grid_repository.h"
#include "../common/repositories/grid_entries_repository.h"
#include "qglobals.h"
#include "spawn2.h"
#include "spawngroup.h"
@@ -203,6 +207,9 @@ public:
std::unordered_map<int, std::unique_ptr<AA::Ability>> aa_abilities;
std::unordered_map<int, std::unique_ptr<AA::Rank>> aa_ranks;
std::vector<GridRepository::Grid> zone_grids;
std::vector<GridEntriesRepository::GridEntry> zone_grid_entries;
time_t weather_timer;
Timer spawn2_timer;
Timer hot_reload_timer;
@@ -240,6 +247,7 @@ public:
void LoadLDoNTrapEntries();
void LoadLDoNTraps();
void LoadLevelEXPMods();
void LoadGrids();
void LoadMercSpells();
void LoadMercTemplates();
void LoadNewMerchantData(uint32 merchantid);
@@ -253,7 +261,6 @@ public:
void RemoveAuth(const char *iCharName, const char *iLSKey);
void RemoveAuth(uint32 lsid);
void Repop(uint32 delay = 0);
void RepopClose(const glm::vec4 &client_position, uint32 repop_distance);
void RequestUCSServerStatus();
void ResetAuth();
void SetDate(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute);
@@ -279,6 +286,7 @@ public:
ZonePoint *GetClosestZonePoint(const glm::vec3 &location, uint32 to, Client *client, float max_distance = 40000.0f);
ZonePoint *GetClosestZonePointWithoutZone(float x, float y, float z, Client *client, float max_distance = 40000.0f);
Timer GetInitgridsTimer();
uint32 GetInstanceTimeRemaining() const;
void SetInstanceTimeRemaining(uint32 instance_time_remaining);
@@ -349,8 +357,6 @@ private:
bool staticzone;
bool zone_has_current_time;
bool quest_hot_reload_queued;
private:
double max_movement_update_range;
char *long_name;
char *map_name;
@@ -370,8 +376,6 @@ private:
uint32 pMaxClients;
uint32 zoneid;
uint32 m_last_ucss_update;
uint32 pQueuedMerchantsWorkID;
uint32 pQueuedTempMerchantsWorkID;
GlobalLootManager m_global_loot;
LinkedList<ZoneClientAuth_Struct *> client_auth_list;
@@ -384,7 +388,7 @@ private:
Timer autoshutdown_timer;
Timer clientauth_timer;
Timer hotzone_timer;
Timer initgrids_timer; //delayed loading of initial grids.
Timer initgrids_timer;
Timer qglobal_purge_timer;
ZoneSpellsBlocked *blocked_spells;
+193
View File
@@ -0,0 +1,193 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "zone_store.h"
#include "../common/repositories/content_flags_repository.h"
#include "../common/content/world_content_service.h"
ZoneStore::ZoneStore() = default;
ZoneStore::~ZoneStore() = default;
void ZoneStore::LoadZones()
{
zones = ZoneRepository::All();
}
/**
* @param in_zone_name
* @return
*/
uint32 ZoneStore::GetZoneID(const char *in_zone_name)
{
if (in_zone_name == nullptr) {
return 0;
}
std::string zone_name = str_tolower(in_zone_name);
return GetZoneID(zone_name);
}
/**
* @param zone_name
* @return
*/
uint32 ZoneStore::GetZoneID(std::string zone_name)
{
for (auto &z: zones) {
if (z.short_name == zone_name) {
return z.zoneidnumber;
}
}
return 0;
}
/**
* @param zone_id
* @param error_unknown
* @return
*/
const char *ZoneStore::GetZoneName(uint32 zone_id, bool error_unknown)
{
for (auto &z: zones) {
if (z.zoneidnumber == zone_id) {
return z.short_name.c_str();
}
}
if (error_unknown) {
return "UNKNOWN";
}
return nullptr;
}
/**
* @param zone_id
* @return
*/
std::string ZoneStore::GetZoneName(uint32 zone_id)
{
for (auto &z: zones) {
if (z.zoneidnumber == zone_id) {
return z.short_name;
}
}
return std::string();
}
/**
* @param zone_id
* @return
*/
std::string ZoneStore::GetZoneLongName(uint32 zone_id)
{
for (auto &z: zones) {
if (z.zoneidnumber == zone_id) {
return z.long_name;
}
}
return std::string();
}
/**
* @param zone_id
* @param version
* @return
*/
ZoneRepository::Zone ZoneStore::GetZone(uint32 zone_id, int version)
{
for (auto &z: zones) {
if (z.zoneidnumber == zone_id && z.version == version) {
return z;
}
}
return ZoneRepository::Zone();
}
/**
* @param in_zone_name
* @return
*/
ZoneRepository::Zone ZoneStore::GetZone(const char *in_zone_name)
{
for (auto &z: zones) {
if (z.short_name == in_zone_name) {
return z;
}
}
return ZoneRepository::Zone();
}
/**
* @return
*/
void ZoneStore::LoadContentFlags()
{
std::vector<std::string> set_content_flags;
auto content_flags = ContentFlagsRepository::GetWhere("enabled = 1");
set_content_flags.reserve(content_flags.size());
for (auto &flags: content_flags) {
set_content_flags.push_back(flags.flag_name);
}
LogInfo(
"Enabled content flags [{}]",
implode(", ", set_content_flags)
);
content_service.SetContentFlags(set_content_flags);
}
/**
* Sets the value in the database and proceeds to load content flags into the server context again
*
* @param content_flag_name
* @param enabled
*/
void ZoneStore::SetContentFlag(const std::string &content_flag_name, bool enabled)
{
auto content_flags = ContentFlagsRepository::GetWhere(
fmt::format("flag_name = '{}'", content_flag_name)
);
auto content_flag = ContentFlagsRepository::NewEntity();
if (!content_flags.empty()) {
content_flag = content_flags.front();
}
content_flag.enabled = enabled ? 1 : 0;
content_flag.flag_name = content_flag_name;
if (!content_flags.empty()) {
ContentFlagsRepository::UpdateOne(content_flag);
}
else {
ContentFlagsRepository::InsertOne(content_flag);
}
LoadContentFlags();
}
+67
View File
@@ -0,0 +1,67 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef EQEMU_ZONE_STORE_H
#define EQEMU_ZONE_STORE_H
#include "zonedb.h"
#include "../common/repositories/zone_repository.h"
#include "../common/repositories/base/base_content_flags_repository.h"
class ZoneStore {
public:
ZoneStore();
virtual ~ZoneStore();
std::vector<ZoneRepository::Zone> zones;
void LoadZones();
ZoneRepository::Zone GetZone(uint32 zone_id, int version = 0);
ZoneRepository::Zone GetZone(const char *in_zone_name);
uint32 GetZoneID(const char *in_zone_name);
uint32 GetZoneID(std::string zone_name);
std::string GetZoneName(uint32 zone_id);
std::string GetZoneLongName(uint32 zone_id);
const char *GetZoneName(uint32 zone_id, bool error_unknown = false);
static void LoadContentFlags();
static void SetContentFlag(const std::string& content_flag_name, bool enabled);
};
extern ZoneStore zone_store;
/**
* Global helpers
*/
inline uint32 ZoneID(const char *in_zone_name) { return zone_store.GetZoneID(in_zone_name); }
inline uint32 ZoneID(std::string zone_name) { return zone_store.GetZoneID(zone_name); }
inline const char *ZoneName(uint32 zone_id, bool error_unknown = false)
{
return zone_store.GetZoneName(
zone_id,
error_unknown
);
}
inline const char *ZoneLongName(uint32 zone_id) { return zone_store.GetZoneLongName(zone_id).c_str(); }
inline ZoneRepository::Zone GetZone(uint32 zone_id, int version = 0) { return zone_store.GetZone(zone_id, version); };
inline ZoneRepository::Zone GetZone(const char *in_zone_name) { return zone_store.GetZone(in_zone_name); };
#endif //EQEMU_ZONE_STORE_H
+61 -45
View File
@@ -11,7 +11,9 @@
#include "merc.h"
#include "zone.h"
#include "zonedb.h"
#include "zone_store.h"
#include "aura.h"
#include "../common/repositories/criteria/content_filter_criteria.h"
#include <ctime>
#include <iostream>
@@ -20,6 +22,7 @@
extern Zone* zone;
ZoneDatabase database;
ZoneDatabase content_db;
ZoneDatabase::ZoneDatabase()
: SharedDatabase()
@@ -82,19 +85,19 @@ bool ZoneDatabase::SaveZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct
}
bool ZoneDatabase::GetZoneCFG(
uint32 zoneid,
uint16 instance_id,
NewZone_Struct *zone_data,
bool &can_bind,
bool &can_combat,
bool &can_levitate,
bool &can_castoutdoor,
bool &is_city,
bool &is_hotzone,
bool &allow_mercs,
uint32 zoneid,
uint16 instance_id,
NewZone_Struct *zone_data,
bool &can_bind,
bool &can_combat,
bool &can_levitate,
bool &can_castoutdoor,
bool &is_city,
bool &is_hotzone,
bool &allow_mercs,
double &max_movement_update_range,
uint8 &zone_type,
int &ruleset,
uint8 &zone_type,
int &ruleset,
char **map_filename) {
*map_filename = new char[100];
@@ -164,8 +167,11 @@ bool ZoneDatabase::GetZoneCFG(
"fast_regen_endurance, " // 59
"npc_max_aggro_dist, " // 60
"max_movement_update_range " // 61
"FROM zone WHERE zoneidnumber = %i AND version = %i",
zoneid, instance_id);
"FROM zone WHERE zoneidnumber = %i AND version = %i %s",
zoneid,
instance_id,
ContentFilterCriteria::apply().c_str()
);
auto results = QueryDatabase(query);
if (!results.Success()) {
strcpy(*map_filename, "default");
@@ -360,7 +366,7 @@ void ZoneDatabase::RegisterBug(BugReport_Struct* bug_report) {
char* type_ = nullptr;
char* target_ = nullptr;
char* bug_ = nullptr;
len = strlen(bug_report->reporter_name);
if (len) {
if (len > 63) // check against db column size
@@ -426,7 +432,7 @@ void ZoneDatabase::RegisterBug(BugReport_Struct* bug_report) {
safe_delete_array(type_);
safe_delete_array(target_);
safe_delete_array(bug_);
QueryDatabase(query);
}
@@ -584,7 +590,7 @@ void ZoneDatabase::RegisterBug(Client* client, BugReport_Struct* bug_report) {
safe_delete_array(target_name_);
safe_delete_array(bug_report_);
safe_delete_array(system_info_);
auto result = QueryDatabase(query);
// TODO: Entity dumping [RuleB(Bugs, DumpTargetEntity)]
@@ -750,27 +756,37 @@ void ZoneDatabase::SaveWorldContainer(uint32 zone_id, uint32 parent_id, const EQ
}
}
std::string query = StringFormat("REPLACE INTO object_contents "
"(zoneid, parentid, bagidx, itemid, charges, "
"augslot1, augslot2, augslot3, augslot4, augslot5, augslot6, droptime) "
"VALUES (%i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i, now())",
zone_id, parent_id, index, item_id, inst->GetCharges(),
augslot[0], augslot[1], augslot[2], augslot[3], augslot[4], augslot[5]);
auto results = QueryDatabase(query);
if (!results.Success())
LogError("Error in ZoneDatabase::SaveWorldContainer: [{}]", results.ErrorMessage().c_str());
std::string query = StringFormat(
"REPLACE INTO object_contents "
"(zoneid, parentid, bagidx, itemid, charges, "
"augslot1, augslot2, augslot3, augslot4, augslot5, augslot6, droptime) "
"VALUES (%i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i, now())",
zone_id, parent_id, index, item_id, inst->GetCharges(),
augslot[0], augslot[1], augslot[2], augslot[3], augslot[4], augslot[5]
);
}
auto results = database.QueryDatabase(query);
if (!results.Success()) {
LogError("Error in ZoneDatabase::SaveWorldContainer: [{}]", results.ErrorMessage().c_str());
}
}
}
// Remove all child objects inside a world container (i.e., forge, bag dropped to ground, etc)
void ZoneDatabase::DeleteWorldContainer(uint32 parent_id, uint32 zone_id)
{
std::string query = StringFormat("DELETE FROM object_contents WHERE parentid = %i AND zoneid = %i", parent_id, zone_id);
auto results = QueryDatabase(query);
if (!results.Success())
std::string query = StringFormat(
"DELETE FROM object_contents WHERE parentid = %i AND zoneid = %i",
parent_id,
zone_id
);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
LogError("Error in ZoneDatabase::DeleteWorldContainer: [{}]", results.ErrorMessage().c_str());
}
}
@@ -1243,9 +1259,9 @@ bool ZoneDatabase::LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Str
"`character_spells` "
"WHERE `id` = %u ORDER BY `slot_id`", character_id);
auto results = database.QueryDatabase(query);
/* Initialize Spells */
memset(pp->spell_book, 0xFF, (sizeof(uint32) * EQ::spells::SPELLBOOK_SIZE));
// We have the ability to block loaded spells by max id on a per-client basis..
@@ -1261,7 +1277,7 @@ bool ZoneDatabase::LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Str
continue;
if (id < 3 || id > SPDAT_RECORDS) // 3 ("Summon Corpse") is the first scribable spell in spells_us.txt
continue;
pp->spell_book[idx] = id;
}
@@ -1605,11 +1621,11 @@ bool ZoneDatabase::SaveCharacterLeadershipAA(uint32 character_id, PlayerProfile_
}
bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp){
/* If this is ever zero - the client hasn't fully loaded and potentially crashed during zone */
if (account_id <= 0)
return false;
std::string mail_key = database.GetMailKey(character_id);
clock_t t = std::clock(); /* Function timer start */
@@ -3551,7 +3567,7 @@ void ZoneDatabase::ListAllInstances(Client* client, uint32 charid)
client->Message(Chat::White, "%s is part of the following instances:", name);
for (auto row = results.begin(); row != results.end(); ++row) {
client->Message(Chat::White, "%s - id: %lu, version: %lu", database.GetZoneName(atoi(row[1])),
client->Message(Chat::White, "%s - id: %lu, version: %lu", ZoneName(atoi(row[1])),
(unsigned long)atoi(row[0]), (unsigned long)atoi(row[2]));
}
}
@@ -4089,9 +4105,9 @@ bool ZoneDatabase::LoadFactionData()
faction_array = new Faction *[max_faction + 1];
memset(faction_array, 0, (sizeof(Faction*) * (max_faction + 1)));
std::vector<size_t> faction_ids;
std::vector<std::string> faction_ids;
// load factions
query = "SELECT `id`, `name`, `base` FROM `faction_list`";
@@ -4119,13 +4135,13 @@ bool ZoneDatabase::LoadFactionData()
faction_array[index]->base = atoi(fr_row[2]);
faction_array[index]->min = MIN_PERSONAL_FACTION;
faction_array[index]->max = MAX_PERSONAL_FACTION;
faction_ids.push_back(index);
faction_ids.push_back(fr_row[0]);
}
LogInfo("[{}] Faction(s) loaded...", faction_ids.size());
const std::string faction_id_criteria(implode(",", std::pair<char, char>('\'', '\''), faction_ids));
const std::string faction_id_criteria(implode(",", faction_ids));
// load faction mins/maxes
query = fmt::format("SELECT `client_faction_id`, `min`, `max` FROM `faction_base_data` WHERE `client_faction_id` IN ({})", faction_id_criteria);
@@ -4155,7 +4171,7 @@ bool ZoneDatabase::LoadFactionData()
else {
LogInfo("Unable to load Faction Base data...");
}
// load race, class and diety modifiers
query = fmt::format("SELECT `faction_id`, `mod`, `mod_name` FROM `faction_list_mod` WHERE `faction_id` IN ({})", faction_id_criteria);
@@ -4878,7 +4894,7 @@ uint32 ZoneDatabase::LoadSaylinkID(const char* saylink_text, bool auto_insert)
{
if (!saylink_text || saylink_text[0] == '\0')
return 0;
std::string query = StringFormat("SELECT `id` FROM `saylink` WHERE `phrase` = '%s' LIMIT 1", saylink_text);
auto results = QueryDatabase(query);
if (!results.Success())
@@ -4903,6 +4919,6 @@ uint32 ZoneDatabase::SaveSaylinkID(const char* saylink_text)
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
return results.LastInsertedID();
}
+1 -2
View File
@@ -503,8 +503,6 @@ public:
bool DoorIsOpen(uint8 door_id,const char* zone_name);
void SetDoorPlace(uint8 value,uint8 door_id,const char* zone_name);
bool LoadDoors(int32 door_count, Door *into, const char *zone_name, int16 version);
bool CheckGuildDoor(uint8 doorid,uint16 guild_id, const char* zone);
bool SetGuildDoor(uint8 doorid,uint16 guild_id, const char* zone);
uint32 GetGuildEQID(uint32 guilddbid);
void UpdateDoorGuildID(int doorid, int guild_id);
int32 GetDoorsCount(uint32* oMaxID, const char *zone_name, int16 version);
@@ -577,6 +575,7 @@ protected:
};
extern ZoneDatabase database;
extern ZoneDatabase content_db;
#endif /*ZONEDB_H_*/
+66 -14
View File
@@ -35,6 +35,9 @@ extern QueryServ* QServ;
extern WorldServer worldserver;
extern Zone* zone;
#include "../common/repositories/zone_repository.h"
#include "../common/content/world_content_service.h"
void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
#ifdef BOTS
@@ -156,7 +159,7 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
}
/* Check for Valid Zone */
const char *target_zone_name = database.GetZoneName(target_zone_id);
const char *target_zone_name = ZoneName(target_zone_id);
if(target_zone_name == nullptr) {
//invalid zone...
Message(Chat::Red, "Invalid target zone ID.");
@@ -170,7 +173,7 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
int16 minstatus = 0;
uint8 minlevel = 0;
char flag_needed[128];
if(!database.GetSafePoints(target_zone_name, database.GetInstanceVersion(target_instance_id), &safe_x, &safe_y, &safe_z, &minstatus, &minlevel, flag_needed)) {
if(!content_db.GetSafePoints(target_zone_name, database.GetInstanceVersion(target_instance_id), &safe_x, &safe_y, &safe_z, &minstatus, &minlevel, flag_needed)) {
//invalid zone...
Message(Chat::Red, "Invalid target zone while getting safe points.");
LogError("Zoning [{}]: Unable to get safe coordinates for zone [{}]", GetName(), target_zone_name);
@@ -284,6 +287,55 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
//TODO: ADVENTURE ENTRANCE CHECK
/**
* Expansion check
*/
if (content_service.GetCurrentExpansion() >= Expansion::Classic && !GetGM()) {
/**
* Hit the zone cache first so we're not hitting the database every time someone attempts to zone
*/
bool meets_zone_expansion_check = false;
bool found_zone = false;
for (auto &z: zone_store.zones) {
if (z.short_name == target_zone_name && z.version == 0) {
found_zone = true;
if (z.expansion <= (content_service.GetCurrentExpansion() + 1)) {
meets_zone_expansion_check = true;
break;
}
}
}
/**
* If we fail to find a cached zone lookup because someone just so happened to change some data, second attempt
* In 99% of cases we would never get here and this would be fallback
*/
if (!found_zone) {
auto zones = ZoneRepository::GetWhere(
fmt::format(
"expansion <= {} AND short_name = '{}' and version = 0",
(content_service.GetCurrentExpansion() + 1),
target_zone_name
)
);
meets_zone_expansion_check = !zones.empty();
}
LogInfo(
"Checking zone request [{}] for expansion [{}] ({}) success [{}]",
target_zone_name,
(content_service.GetCurrentExpansion() + 1),
content_service.GetCurrentExpansionName(),
meets_zone_expansion_check ? "true" : "false"
);
if (!meets_zone_expansion_check) {
myerror = ZONE_ERROR_NOEXPANSION;
}
}
if(myerror == 1) {
//we have successfully zoned
DoZoneSuccess(zc, target_zone_id, target_instance_id, dest_x, dest_y, dest_z, dest_h, ignorerestrictions);
@@ -348,7 +400,7 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc
if(this->GetPet())
entity_list.RemoveFromHateLists(this->GetPet());
LogInfo("Zoning [{}] to: [{}] ([{}]) - ([{}]) x [{}] y [{}] z [{}]", m_pp.name, database.GetZoneName(zone_id), zone_id, instance_id, dest_x, dest_y, dest_z);
LogInfo("Zoning [{}] to: [{}] ([{}]) - ([{}]) x [{}] y [{}] z [{}]", m_pp.name, ZoneName(zone_id), zone_id, instance_id, dest_x, dest_y, dest_z);
//set the player's coordinates in the new zone so they have them
//when they zone into it
@@ -402,7 +454,7 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc
}
void Client::MovePC(const char* zonename, float x, float y, float z, float heading, uint8 ignorerestrictions, ZoneMode zm) {
ProcessMovePC(database.GetZoneID(zonename), 0, x, y, z, heading, ignorerestrictions, zm);
ProcessMovePC(ZoneID(zonename), 0, x, y, z, heading, ignorerestrictions, zm);
}
//designed for in zone moving
@@ -424,7 +476,7 @@ void Client::MoveZone(const char *zone_short_name) {
ztz->response = 0;
ztz->current_zone_id = zone->GetZoneID();
ztz->current_instance_id = zone->GetInstanceID();
ztz->requested_zone_id = database.GetZoneID(zone_short_name);
ztz->requested_zone_id = ZoneID(zone_short_name);
ztz->admin = Admin();
strcpy(ztz->name, GetName());
ztz->guild_id = GuildID();
@@ -571,8 +623,8 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
const char* pShortZoneName = nullptr;
char* pZoneName = nullptr;
pShortZoneName = database.GetZoneName(zoneID);
database.GetZoneLongName(pShortZoneName, &pZoneName);
pShortZoneName = ZoneName(zoneID);
content_db.GetZoneLongName(pShortZoneName, &pZoneName);
if(!pZoneName) {
Message(Chat::Red, "Invalid zone number specified");
@@ -619,7 +671,7 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
heading = m_pp.binds[0].heading;
zonesummon_ignorerestrictions = 1;
LogDebug("Player [{}] has died and will be zoned to bind point in zone: [{}] at LOC x=[{}], y=[{}], z=[{}], heading=[{}]",
LogDebug("Player [{}] has died and will be zoned to bind point in zone: [{}] at LOC x=[{}], y=[{}], z=[{}], heading=[{}]",
GetName(), pZoneName, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, m_pp.binds[0].heading);
break;
case SummonPC:
@@ -628,8 +680,8 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
SetHeading(heading);
break;
case Rewind:
LogDebug("[{}] has requested a /rewind from [{}], [{}], [{}], to [{}], [{}], [{}] in [{}]", GetName(),
m_Position.x, m_Position.y, m_Position.z,
LogDebug("[{}] has requested a /rewind from [{}], [{}], [{}], to [{}], [{}], [{}] in [{}]", GetName(),
m_Position.x, m_Position.y, m_Position.z,
m_RewindLocation.x, m_RewindLocation.y, m_RewindLocation.z, zone->GetShortName());
m_ZoneSummonLocation = glm::vec3(x, y, z);
m_Position = glm::vec4(m_ZoneSummonLocation, 0.0f);
@@ -917,10 +969,10 @@ void Client::SendZoneFlagInfo(Client *to) const {
for(; cur != end; ++cur) {
uint32 zoneid = *cur;
const char *short_name = database.GetZoneName(zoneid);
const char *short_name = ZoneName(zoneid);
char *long_name = nullptr;
database.GetZoneLongName(short_name, &long_name);
content_db.GetZoneLongName(short_name, &long_name);
if(long_name == nullptr)
long_name = empty;
@@ -928,7 +980,7 @@ void Client::SendZoneFlagInfo(Client *to) const {
int16 minstatus = 0;
uint8 minlevel = 0;
char flag_name[128];
if(!database.GetSafePoints(short_name, 0, &safe_x, &safe_y, &safe_z, &minstatus, &minlevel, flag_name)) {
if(!content_db.GetSafePoints(short_name, 0, &safe_x, &safe_y, &safe_z, &minstatus, &minlevel, flag_name)) {
strcpy(flag_name, "(ERROR GETTING NAME)");
}
@@ -950,7 +1002,7 @@ bool Client::CanBeInZone() {
int16 minstatus = 0;
uint8 minlevel = 0;
char flag_needed[128];
if(!database.GetSafePoints(zone->GetShortName(), zone->GetInstanceVersion(), &safe_x, &safe_y, &safe_z, &minstatus, &minlevel, flag_needed)) {
if(!content_db.GetSafePoints(zone->GetShortName(), zone->GetInstanceVersion(), &safe_x, &safe_y, &safe_z, &minstatus, &minlevel, flag_needed)) {
//this should not happen...
LogDebug("[CLIENT] Unable to query zone info for ourself [{}]", zone->GetShortName());
return(false);